OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Четверг, 28 Март, 2024 22:56

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 18 ] 
Автор Сообщение
 Заголовок сообщения: Вникаем в контекст
СообщениеДобавлено: Понедельник, 30 Январь, 2023 19:29 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
маленький общий вопрос, под который отдельную тему создавать как-то… если говорить «околосишными» терминами, то контекст — это, по сути, данные контейнера-родителя, просто хранящиеся не в нём, а во вложеном view? вот, это словами и описать-то сложно. короче, несмотря на то, что `c: Context` описано в некоем view, на самом деле это данные совсем другого view, которые просто таким образом хитро «пристёгивают» к нужному. мигните три раза, если вы поняли, что я тут пытаюсь описать (и заодно помогите, пожалуйста, как-то это описать более внятно).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: BlackBox 2.0
СообщениеДобавлено: Понедельник, 30 Январь, 2023 19:53 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
arisu писал(а):
маленький общий вопрос, под который отдельную тему создавать как-то… если говорить «околосишными» терминами, то контекст — это, по сути, данные контейнера-родителя, просто хранящиеся не в нём, а во вложеном view? вот, это словами и описать-то сложно. короче, несмотря на то, что `c: Context` описано в некоем view, на самом деле это данные совсем другого view, которые просто таким образом хитро «пристёгивают» к нужному. мигните три раза, если вы поняли, что я тут пытаюсь описать (и заодно помогите, пожалуйста, как-то это описать более внятно).


Это внешний объект, который хранит ссылки и на родительский вид и на встроенный.
Цитата:
Объект контекста является частью рекурсивной схемы модель-отображение, принятой в BlackBox. Контекст создается и поддерживается отображением, так что отображение может сообщаться со своим контекстом (то есть, с моделью, в которую оно внедрено). Context позволяет внедренному отображению сообщаться со своим контейнером.

Мне с этими контекстами помог когда-то разобраться пример ObxTwins.

Чтобы что-то встроить в вид, придётся сделать контекст для этого встраивания, установить размеры. И тогда уже встроенный вид будет знать, какого размера ему надо нарисоваться. Хотя вид может и сам себе размеры через контекст установить. И родительский вид это должен тогда учитывать.

Цитата:
Модель может быть контейнером, то есть, содержать внедренные отображения. Внедренное отображение может сообщаться с моделью, в которую оно внедрено, через Context. Модель контейнера предоставляет контекст для каждого внедренного отображения. Используя этот контекст, отображение может запросить свой текущий размер или попытаться его изменить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Понедельник, 30 Январь, 2023 21:01 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
спасибо. да, я понимаю, зачем он нужен (понял, когда разъединил понятия hold/keep и own), но не могу придумать, как это внятно пояснить вне терминов BBCB. зачем именно вне? ну, попытка сделать пояснение этой механики гипотетическому человеку, который привык к немного другой организации всего; чтобы легче было вникать.

а ObxTwins отличный пример, да. вообще, Obx на удивление кратко, но хорошо поясняют концепции, но… есть нюанс: пока в голове не «щёлкнуло» — всё вместе довольно сложно уложить в стройную композицию. вот я пытаюсь сочинить что-нибудь, что поможет «щёлкнуть».


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Понедельник, 30 Январь, 2023 21:36 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Я понял так, что эта такая важная фишка составных документов. Чтобы обеспечить "слабое связывание". Ведь родительскому виду как-бы всё равно, что там в него встроено. Он как бы говорит, "сынок, будь свободен, давай ограничимся, тем, что будем знать только про геометрические границы, и как тебя вернуть в исходное состояние перед тем, как я буду сохранять тебя на диск, больше мне от тебя ничего не надо". Это как с StdCFrames, он также очень сознательно ограничивает, "ослабляет связь" с инструментами.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Вторник, 31 Январь, 2023 07:06 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
я скорее вижу это как прикольный хак (в хорошем смысле слова). по сути, родителю как раз надо знать кое-что про встроеных, причём это знание интимно для родителя, и в общем-то не завязано на конкретный тип того, что встраиваем. если бы в языке было понятие свойств, как в лиспе, например — то это было бы свойство, которое владелец «пристёгивает» к встраиваемым. а так как свойств нет — то это хитро решили при помощи контекста (который есмь то же свойство).

то есть, это немножко хак как раз потому, что получился специализированый механизм пристёгивания свойств к произвольным nested view. но «свойственная» суть контекста очевидна не сразу, до меня вот только дошло, что оно такое на самом деле. теперь надо будет попробовать это как-то внятно выразить. ;-)

p.s.: собственно, что у меня в своё время и вызвало затруднения: несмотря на то, что контекст хранится в nested view, на самом деле это контекст в основном для parent view. такой непривычный разрыв между тем, кто хранит, и кто использует. и, кстати, то, что контекст ещё и за размеры отвечает — не очень помогает. потому что по сути контекст выполняет две не особо связаных функции: передаёт туда-сюда информацию о размерах, и вдобавок служит хранилищем для интимной информации parent view.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Вторник, 31 Январь, 2023 12:40 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Я не понимаю, почему вы пишите, что контекст хранится в дочернем виде, когда он хранится в родительском.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Вторник, 31 Январь, 2023 13:41 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
Иван Денисов писал(а):
Я не понимаю, почему вы пишите, что контекст хранится в дочернем виде, когда он хранится в родительском.
в том-то и шутка, что это как раз совершенно не обязательно (хранить в родительском), и живёт он именно в nested. смотрите:
Код:
   PROCEDURE NewContext (v: Views.View; base: View): Context;
      VAR c: Context;
   BEGIN
      NEW(c);
      c.view := v; c.base := base;
      v.InitContext(c); Stores.Join(v, base);
      RETURN c
   END NewContext;

вот так в ObxTwins создаётся nested view. `v.InitContext()` делает всего лишь: `v.context := context`. и контекст этот, созданый, содержит информацию, которая нужна как раз родителю. и в родителе как раз его можно не кэшировать, а попросить у nested и кастануть во что надо. ObxTwins кэширует, но это чисто для удобства: основное место проживания у созданого контекста именно nested view, код можно переделать так, чтобы `top` и `bottom` были Views.View, и брать контексты из них. вот, собственно, так переделать:
Код:
   TYPE
      Identity = POINTER TO RECORD (Models.Model) END;   (* dummy model *)

      Context = POINTER TO RECORD (Models.Context)
         base: View;         (* container view *)
         view: Views.View;   (* contained view *)
         l, t, r, b: INTEGER   (* cached bounding box of contained view *)
      END;

      View = POINTER TO RECORD (Views.View)
         top, bottom: Views.View;
         ident: Identity;   (* temporary dummy model *)
         focus: Context   (* current focus; either top or bottom *)
      END;


   (* Context *)

   PROCEDURE (c: Context) ThisModel (): Models.Model;
   BEGIN
      RETURN NIL   (* don't give the embedded views information about the dummy twin model *)
   END ThisModel;

   PROCEDURE (c: Context) GetSize (OUT w, h: INTEGER);
   BEGIN
      w := c.r - c.l;
      h := c.b - c.t
   END GetSize;

   PROCEDURE (c: Context) MakeVisible (l, t, r, b: INTEGER);
      VAR w, h, sep: INTEGER;
   BEGIN
      IF c.base.top.context = c THEN   (* top view *)
         c.base.context.MakeVisible(l + border, t + border, r + border, b + border)
      ELSE   (* bottom view *)
         c.base.context.GetSize(w, h); sep := h DIV 3;
         c.base.context.MakeVisible(l + border, t + sep + border, r + border, b + sep + border)
      END
   END MakeVisible;

   PROCEDURE (c: Context) Consider (VAR p: Models.Proposal);
   BEGIN
      c.base.context.Consider(p)
   END Consider;

   PROCEDURE (c: Context) Normalize (): BOOLEAN;
   BEGIN
      RETURN c.base.context.Normalize()
   END Normalize;

   PROCEDURE NewContext (v: Views.View; base: View): Views.View;
      VAR c: Context;
   BEGIN
      NEW(c);
      c.view := v; c.base := base;
      v.InitContext(c); Stores.Join(v, base);
      RETURN v
   END NewContext;

   PROCEDURE CopyOf (source: Views.View; shallow: BOOLEAN; base: View): Views.View;
      VAR v: Views.View;
   BEGIN
      v := Views.CopyOf(source,  shallow);
      RETURN NewContext(v, base)
   END CopyOf;


   (* View *)

   PROCEDURE RecalcLayout (v: View);
      VAR w, h, sep: INTEGER; c: Context;
   BEGIN
      v.context.GetSize(w, h);
      sep := h DIV 3;   (* separate the two views at 1/3 of the container's height *)
      c := v.top.context(Context); c.l := border; c.t := border; c.r := w - border; c.b := sep - border;
      c := v.bottom.context(Context); c.l := border; c.t := sep + border; c.r := w - border; c.b := h - border
   END RecalcLayout;

   PROCEDURE SetFocus (v: Views.View; x, y: INTEGER): BOOLEAN;
      VAR p: Properties.FocusPref;
   BEGIN   (* determine whether v should be focused when the mouse is clicked at (x, y) in v *)
      p.hotFocus := FALSE;
      p.atLocation := TRUE; p.x := x; p.y := y;
      p.setFocus := FALSE;
      Views.HandlePropMsg(v, p);
      RETURN p.setFocus
   END SetFocus;

   PROCEDURE (v: View) CopyFromModelView (source: Views.View; model: Models.Model);
      VAR shallow: BOOLEAN;
   BEGIN
      WITH source: View DO
         shallow := model = source.ident;   (* shallow copy if both views share the same model *)
         Stores.Join(v, model);
         v.top := CopyOf(source.top, shallow, v);
         v.bottom := CopyOf(source.bottom, shallow, v);
         v.ident := model(Identity);
         v.focus := v.bottom.context(Context)
      END
   END CopyFromModelView;

   PROCEDURE (v: View) Internalize (VAR rd: Stores.Reader);
      VAR version: INTEGER; h: Views.View;
   BEGIN
      rd.ReadVersion(minVersion, maxVersion, version);
      IF ~rd.cancelled THEN
         Views.ReadView(rd, h); v.top := NewContext(h, v);
         Views.ReadView(rd, h); v.bottom := NewContext(h, v);
         NEW(v.ident); Stores.Join(v, v.ident);
         v.focus := v.bottom.context(Context)
      END
   END Internalize;

   PROCEDURE (v: View) Externalize (VAR wr: Stores.Writer);
   BEGIN
      wr.WriteVersion(maxVersion);
      Views.WriteView(wr, v.top);
      Views.WriteView(wr, v.bottom)
   END Externalize;

   PROCEDURE (v: View) Neutralize;
   BEGIN
      v.focus.view.Neutralize
   END Neutralize;

   PROCEDURE (v: View) ThisModel (): Models.Model;
   BEGIN
      RETURN v.ident
   END ThisModel;

   PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
      VAR d: INTEGER; c: Context;
   BEGIN
      RecalcLayout(v);
      (* install the subframes for the subviews *)
      c := v.top.context(Context); Views.InstallFrame(f, c.view, c.l, c.t, 0, v.focus = c);
      c := v.bottom.context(Context); Views.InstallFrame(f, c.view, c.l, c.t, 1, v.focus = c);
      (* draw frame around the subviews *)
      d := 2 * f.dot;
      c := v.top.context(Context);
      IF (c.t - d < c.b + d) & (c.l - d < c.r + d) THEN f.DrawRect(c.l - d, c.t - d, c.r + d, c.b + d, f.dot, Ports.black) END;
      c := v.bottom.context(Context);
      IF (c.t - d < c.b + d) & (c.l - d < c.r + d) THEN f.DrawRect(c.l - d, c.t - d, c.r + d, c.b + d, f.dot, Ports.black) END
   END Restore;

   PROCEDURE (v: View) HandleCtrlMsg (f: Views.Frame; VAR msg: Views.CtrlMessage;
                                             VAR focus: Views.View);
      VAR g: Views.Frame; newFocus: Context; mMsg: Controllers.MarkMsg;
         w, h, sep: INTEGER;
   BEGIN
      WITH msg: Controllers.CursorMessage DO
         v.context.GetSize(w, h);
         sep := h DIV 3;
         IF msg.y >= sep THEN newFocus := v.bottom.context(Context) ELSE newFocus := v.top.context(Context) END;
         focus := newFocus.view;
         IF (newFocus # v.focus) & ((msg IS Controllers.TrackMsg) OR (msg IS Controllers.DropMsg)) &
            SetFocus(focus, msg.x, msg.y) THEN
            (* remove marks in old focus *)
            mMsg.show := FALSE; mMsg.focus := TRUE;
            g := Views.ThisFrame(f, v.focus.view); IF g # NIL THEN Views.ForwardCtrlMsg(g, mMsg) END;
            v.focus := newFocus;   (* set new focus *)
            (* set marks in new focus *)
            mMsg.show := TRUE; mMsg.focus := TRUE;
            g := Views.ThisFrame(f, v.focus.view); IF g # NIL THEN Views.ForwardCtrlMsg(g, mMsg) END
         END
      (* the following scrolling-oriented messages are always sent to bottom view, independent of focus *)
      | msg: Controllers.PollSectionMsg DO
         g := Views.ThisFrame(f, v.bottom); IF g # NIL THEN Views.ForwardCtrlMsg(g, msg) END;
         IF msg.vertical & ~msg.done THEN
            msg.valid := FALSE; msg.done := TRUE   (* disable default-scrolling *)
         END
      | msg: Controllers.ScrollMsg DO
         g := Views.ThisFrame(f, v.bottom); IF g # NIL THEN Views.ForwardCtrlMsg(g, msg) END;
         IF msg.vertical THEN msg.done := TRUE END
      | msg: Controllers.PageMsg DO
         focus := v.bottom
      ELSE   (* all other messages are sent to the focus, however *)
         focus := v.focus.view
      END
      (* the assignment to focus signals that the view v wants to forward the message to the
      corresponding embedded view *)
   END HandleCtrlMsg;

   PROCEDURE (v: View) HandlePropMsg (VAR msg: Views.PropMessage);
      CONST defW = 80 * Ports.mm; defH = 60 * Ports.mm;
   BEGIN
      WITH msg: Properties.SizePref DO
         IF msg.w = Views.undefined THEN msg.w := defW END;
         IF msg.h = Views.undefined THEN msg.h := defH END
      | msg: Properties.ResizePref DO
         msg.verFitToWin := TRUE   (* make view always as high as window *)
      ELSE
         Views.HandlePropMsg(v.bottom, msg)
      END
   END HandlePropMsg;

   PROCEDURE (v: View) ConsiderFocusRequestBy (view: Views.View);
   BEGIN
      IF view = v.top THEN
         v.focus := v.top.context(Context)
      ELSIF view = v.bottom THEN
         v.focus := v.bottom.context(Context)
      ELSE
         HALT(20)
      END
   END ConsiderFocusRequestBy;

   PROCEDURE NewTwin* (top, bottom: Views.View): Views.View;
      VAR v: View;
   BEGIN
      NEW(v);
      v.top := NewContext(top, v); v.bottom := NewContext(bottom, v);
      NEW(v.ident); Stores.Join(v, v.ident); v.focus := v.bottom.context(Context);
      RETURN v
   END NewTwin;

вуаля: главный контейнер больше не хранит контексты, а получает их у nested views.

то есть, для кода он доступен (и с точки зрения кода, хранится) именно у nested. но нужен — parent. вот такая вот заковыка, которая может немножко сломать мозг.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Вторник, 31 Январь, 2023 13:58 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
А, понимаю понемногу о чем вы. Да действительно в родителе она только кэшируется. И тут ещё такой важный момент, что виды видами, а еще ведь есть модели. И через контекст как раз получается модель встроенного вида, чтобы её на диск записывать. Так как через взаимодействие с отображением меняется модель встроенного отображения, и родительский вид может эти модели получить через контекст.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Вторник, 31 Январь, 2023 14:05 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
ага. вот и получается — как я писал выше, — что контекст нагружен несколькими логически вроде бы связаными, но на самом деле довольно независимыми функциями. лично мне это поначалу мешало понять, что же такое контекст, чей он, где, куда… когда я, наконец, понял, что это комплексная штука, которая заведует сразу несколькими вещами, и в голове логически её поделил — сразу всё стало ясно (ну, почти сразу ;-). поскольку у меня есть опыт как использования, так и написания гуёв на других языках, и такой подход там встречается не то чтобы — мягко говоря — часто, я предполагаю, что не у одного меня могут мозги свариться. вот и думаю, как бы это попонятней описать для такого же не новичка в программировании, но новичка в BBCB.

p.s.: я не помню, смог ли я это понять 15 лет назад, но даже если и смог — с тех пор прочно забыл, пришлось заново въезжать. ;-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Вторник, 31 Январь, 2023 15:43 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Ещё для полноты картины сюда в тему вставлю кусок документации.

Цитата:
Заметьте интересную связь между моделью и внедренным отображением: объект контекста. Он описывает положение и, возможно, другие атрибуты одного внедренного отображения. Тип контекста определяется контейнером. Контекст создается контейнером, когда отображение внедряется. Внедренное отображение может спросить свой контекст о своем положении в контейнере и может даже получить большую информацию. Например, контекст текстового контейнера может обеспечить информацию о позиции внедренного отображения в тексте (индекс символа), о его текущем шрифте и цвете и т.д.
Внедренное отображение может использовать свой объект контекста не только для получения информации о контейнере, оно может также заставить контейнер выполнить некоторое действие. Например, внедренное отображение может попросить контейнер через объект контекста уменьшить или увеличить себя. Контейнеры могут выполнить подобные запросы или проигнорировать их. В переговорах между контейнером и одним из его внедренных отображений контейнер всегда выигрывает. Например, контейнер не позволяет внедренному отображению стать шире, чем сам контейнер.
Объект контекста можно рассматривать как интерфейс обратного вызова, который контейнер устанавливает во внедренном отображении как подключаемый модуль, поэтому отображение может обратиться к контейнеру и получить его сервисы. Контекст — часть механизма оповещения, который позволяет контейнеру просматривать сообщения от содержащихся отображений.
В последующих рисунках объекты контекста не изображены явно, чтобы рисунки было легче понимать. Просто помните, что каждое отображение носит контекст, который оно может использовать по необходимости.


Вложение:
context.png
context.png [ 13.87 КБ | Просмотров: 3693 ]


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 03:07 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 660
Контекст - это переменная (или интерфейс), предназначенная для расцепления decoupling вида и его контейнера.
Контекст не хранится ни в виде, ни в контейнере - это отдельная динамическая переменная, она может пережить вид, а может пережить контейнер.
Контекст не обязательно содержит размеры вида. Вполне себе эти размеры могут вычисляться на ходу, или быть фиксированными навсегда.
Контекст (точнее, контейнер) не обязан удовлетворять запрос вида (или третьего лица) на изменение размера. Вполне себе может игнорировать.
Контекст содержит замечательную PROCEDURE Consider (VAR p: Models.Proposal), которая позволяет расширять и создавать произвольные интерфейсы для разнообразных запросов от вида к его контейнеру. Т.е. виды имеют право направлять свои предложения на рассмотрение своему контексту. Я этим пользуюсь в StdMenus/StdDocuments, и в др. проектах.

Технически появление контекста можно объяснить так: куда приделать процедуру GetSize и Consider? Так, чтобы любой вид мог ее у своего контейнера вызвать? К Model или к View? Или сделать им общий базовый класс - Stores -> Container -> a) View b) Model? И какого типа сделать поле у View с указателем на контейнер?
Контекст красиво решает эту задачу.

А вот еще есть один пример в ББ, где вид вставляется и не в View и не в Model. И даже не в Store. Документы вставляются в окна. А окно - это само по себе, не вид, не модель, не Store.

На мой взгляд, это чрезвычайно изящное и простое решение, существенно упростившее каркас. И кто его придумал - чел с большой головой. Я бы, наверняка, общий базовый тип бы ввел.
Я не спец по всяким прочим графическим фв (потому что, как нашел ББ в 90х, так больше ничего и не искал), и ума не приложу и не вспомню, как там без контексов обходятся. Время от времени натыкаюсь на горе-обучалки, где делают кнопку, и перво-наперво объясняют, что "кнопка должна иметь размер", а иногда прям и "кнопка должна знать свое положение". С децтва ломают.
Недавно слушал Алена Голуба про agile, он там повышал квалификацию уже квалифицированным спецам и пояснял за революционную идею: что контроллерное сообщение должно сначала попадать к контейнеру, и только он уже должен решать, кому из вложенных видов дальше его направить. Порадовался я за себя, поблагодарил за ББ.

И, кстати, контекст - это не данные.
Код:
TYPE
   Context = POINTER TO ABSTRACT RECORD
      (c: Context) Consider (VAR p: Models.Proposal), NEW, EMPTY;
      (c: Context) GetSize (OUT w, h: INTEGER), NEW, ABSTRACT;
      (c: Context) MakeVisible (l, t, r, b: INTEGER), NEW, EMPTY;
      (c: Context) Normalize (): BOOLEAN, NEW, ABSTRACT;
      (c: Context) SetSize (w, h: INTEGER), NEW, EMPTY;
      (c: Context) ThisModel (): Models.Model, NEW, ABSTRACT
   END;

Тут нет данных, тут абстрактный интерфейс.


Последний раз редактировалось adimetrius Суббота, 04 Февраль, 2023 03:13, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 03:10 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 660
Коллеги вот это
Цитата:
Объект контекста можно рассматривать как интерфейс обратного вызова, который контейнер устанавливает во внедренном отображении как подключаемый модуль, поэтому отображение может обратиться к контейнеру и получить его сервисы. Контекст — часть механизма оповещения, который позволяет контейнеру просматривать сообщения от содержащихся отображений.

для меня читается как словесный салат. Если бы не знал, о чем речь идет - вряд ли бы понял. А вам как?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 03:27 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 660
Иван Денисов писал(а):
А, понимаю понемногу о чем вы. Да действительно в родителе она только кэшируется. И тут ещё такой важный момент, что виды видами, а еще ведь есть модели. И через контекст как раз получается модель встроенного вида, чтобы её на диск записывать. Так как через взаимодействие с отображением меняется модель встроенного отображения, и родительский вид может эти модели получить через контекст.


Context.ThisModel() возвращает (или не возвращает) модель, в которую вставлен вид.
Модель вставленного вида v возвращает v.ThisModel(). ФВ постоянно спрашивает у видов, какую модель они отображают. ФВ никогда (или почти никогда) не спрашивает у контекстов, к каким моделям они относятся. Экстернализация производится вообще без обращения к ThisModel.

Не стоит тж забывать, что один контекст может использоваться несколькими видами одновременно. Некоторые виды-обертки так работают (в том случае, если они должны совпадать по размерам с обернутыми видами). Но у одного вида один и только один контекст (даже если виду выделено несколько кадров, т.е. он нарисован на экране несколько раз).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 09:28 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
adimetrius писал(а):
Контекст не хранится ни в виде, ни в контейнере - это отдельная динамическая переменная, она может пережить вид, а может пережить контейнер.
да, логически это именно так. но я говорил про то, что в View есть `c-: Context`, что автоматически включает рефлекс: «ага, значит, оно хранится здесь!» и именно этот рефлекс затрудняет понимание. я хоть и не первый день с GC живу, но всё равно трудно иногда разделить понятия «хранение» и «ссылка, одна из многих равных». раз тут поле описано — значит, тут и хозяин. ;-)

adimetrius писал(а):
На мой взгляд, это чрезвычайно изящное и простое решение, существенно упростившее каркас. И кто его придумал - чел с большой головой. Я бы, наверняка, общий базовый тип бы ввел.
да, решение великолепное. но шибко непривычное, особенно если уже испорчен другими фрэймворками.

adimetrius писал(а):
Я не спец по всяким прочим графическим фв (потому что, как нашел ББ в 90х, так больше ничего и не искал), и ума не приложу и не вспомню, как там без контексов обходятся.
СТРАДАЮТ, по большей части.

adimetrius писал(а):
Время от времени натыкаюсь на горе-обучалки, где делают кнопку, и перво-наперво объясняют, что "кнопка должна иметь размер", а иногда прям и "кнопка должна знать свое положение". С децтва ломают.
ну, это совсем какие-то… печальные. у большинства нормальных тулкитов есть размеры по умолчанию, и min/max/preferred constraints. обычно прибиты гвоздиками как поля к некоторому базовому типу.

adimetrius писал(а):
и пояснял за революционную идею: что контроллерное сообщение должно сначала попадать к контейнеру, и только он уже должен решать, кому из вложенных видов дальше его направить.
даже революционная идея sink/bubble из DOM всё ещё не стала стандартом: во многих местах продолжают делать диспетчер «от солнца в фокус», и городить сбоку механизмы перехвата сообщений.

признаюсь, что я тоже тупой: хоть sink/bubble в своих тулкитах и использую, но всё ещё заранее создаю пути до фокуса, вместо чтобы позволить это решать контейнерам. в BBCB сделано намного изящней.

adimetrius писал(а):
И, кстати, контекст - это не данные.
технически это «абстрактные данные». ;-) ну, в смысле, интерфейс явно подразумевает, какого рода данными контекст должен управлять, но не навязывает форму их хранения. но это я так, чисто от общего недовольства терминологией (не только русскоязычной).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 09:34 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
adimetrius писал(а):
Коллеги вот это
Цитата:
Объект контекста можно рассматривать как интерфейс обратного вызова, который контейнер устанавливает во внедренном отображении как подключаемый модуль, поэтому отображение может обратиться к контейнеру и получить его сервисы. Контекст — часть механизма оповещения, который позволяет контейнеру просматривать сообщения от содержащихся отображений.

для меня читается как словесный салат. Если бы не знал, о чем речь идет - вряд ли бы понял. А вам как?
признаюсь, что я вообще очень плохо читаю канцелярно-академические тексты. и в принципе тексты без уместного мата (которым IRL я разговариваю, а не ругаюсь). с англоязычными почему-то проще, а русскоязычные не лезут никак, разве что переводить их по дороге на английский. это я к тому, что я тоже ничего не понял, но списал это на свои особенности восприятия.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 09:47 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
кстати о птичках. давеча опять сокрушался по поводу отсутствия в BBCB flexbox layouter'а. очень я к нему привык, не хватает. вот только не могу придумать, как для него красиво сделать визуальный редактор. одна из фич layouter'а, который я использую (и обязательно перетащу в BBCB, там кода килобайт восемь) — вычисление размеров формы на основе размеров элементов. надо иметь возможность как руками таскать за якоря, так и указать, что хочется автомат (и чтобы автомат вычислялся и в layout mode). а для этого, чую, надо лезть в Forms. а так лень… ;-)

но надо, потому что я очень устал от того, что надписи в контролы не помещаются. опять таки: у меня зрение плохое, я выбираю шрифт для диалогов побольше — и начинается праздник обрезания. всё это надо переделать на флексы, а контролы обучить выдавать минимальные размеры так, чтобы содержимое поместилось. заодно, кстати, формы станут магически resizeable.

p.s.: ну да, можно ещё просто ресайзить всю форму, пропорционально увеличивая контролы и координаты, но это менее красиво. нормальный layouter лучше, ящитаю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 16:34 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 660
Да, верстальщик (layouter) нужен. Плиточный интерфейс я сделал как частный случай: вид Делитель: делит все свое пространство между своими содержимыми, либо в столбик, либо в строчку; и комбинацией Делителей получается три дорожки, а в левую дорожку окна добавляются "в столбик", а не "блокнотом". Но я сделал его как специальный контейнер, да еще и безмодельный, а не как общий (не как расширение Containers.View/Model). И это требует переделки, расширения от общего контейнера Containers, в т.ч. чтобы были 4 привычных режима Edit Layout Browse Mask и возможность редактировать в диалоговом режиме, а не только программно задавать.

Сложный (для меня) вопрос - точная формулировка правил, по которым содержимые располагаются. Я в этом смысле почитывал про HTML flexbox и еще какой-то там есть, все время забываю название.
Вы про этот flexbox? Вы говорите, что уже есть у вас 8КБ каких-то расчетов?

Предлагаю обсудить такой контейнер и потихоньку его делать.

По терминологии: контейнер - это ведь сборник. А containee - можно "содержимое" в м.р. перевести и пользоваться: содержимый. Есть сборник, есть у него содержимое (неопределенное), а отдельный вид в сборнике - содержимый.
Получается: необходим верстающий сборник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вникаем в контекст
СообщениеДобавлено: Суббота, 04 Февраль, 2023 17:52 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1163
adimetrius писал(а):
Сложный (для меня) вопрос - точная формулировка правил, по которым содержимые располагаются. Я в этом смысле почитывал про HTML flexbox и еще какой-то там есть, все время забываю название.
Вы про этот flexbox? Вы говорите, что уже есть у вас 8КБ каких-то расчетов?
про этот, но очень упрощённый. лично для себя я оставил только простое раскладывание без автопереносов строк, этого в 99% случаев для интерфейсов достаточно. в принципе, мне пока ни разу автопереносы не понадобились. вот вам в аттаче реализация на си: я примерно этот код таскаю на любой язык, где мне понадобился layouter. его же хочу и на CP портировать. (если убрать комментарии и прочее, там около восьми килобайт и получается, плюс-минус северный полюс.)

там написано GPL, но можете считать, что это WTFPL. я как автор даю согласие. ;-)

p.s.: предложение по терминам хорошее. но я всё-таки буду по возможности английские варианты использовать: от русскоязычных у меня оскомина, ничего не могу поделать. канцелярщиной отдаёт. а мои термины вроде «ложилка» (или «лажалка», когда его заглючило; да, я в курсе, что слова «ложить» нет, потому и использовал ;-), «финтифлюшка» (это gadget/widget), и подобные вряд ли стоит использовать Официально. и это ещё самые приличные. ;-)


Вложения:
Комментарий к файлу: FlexLay2/C
flexlay2.7z [7.69 КБ]
Скачиваний: 71
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 18 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB