OberonCore
https://forum.oberoncore.ru/

Элементы меню для документа в обёртке
https://forum.oberoncore.ru/viewtopic.php?f=23&t=2126
Страница 1 из 1

Автор:  GameHunter [ Пятница, 27 Ноябрь, 2009 01:00 ]
Заголовок сообщения:  Элементы меню для документа в обёртке

Уважаемые специалисты,

Я изучаю ББ, пытаюсь написать обёртку для изменения фона документов.
Проблема такая: когда вьюшка документа обёрнута,
некоторые пункты меню, активные без обёртки, не активны.
Например, Dev -> Edit mode, Dev -> Layout mode, ...
В чём дело?

код:

Код:
MODULE MyWrapper;

IMPORT
   Dialog, Stores, Models, Views, Controllers, Properties, Ports;

CONST minVersion = 0; maxVersion = 0;

TYPE
   View = POINTER TO RECORD (Views.View)
      inner: Views.View;
      BackgroundColor:Ports.Color;
   END;

   FindMsg = RECORD (Controllers.Message)
      v:Views.View;
   END;
   
PROCEDURE (v: View) Internalize (VAR rd: Stores.Reader);
   VAR
      version: INTEGER;
   BEGIN
      rd.ReadVersion(minVersion, maxVersion, version);
      IF ~rd.cancelled THEN
         Views.ReadView(rd, v.inner);   (* generate Views.Alien if necessary *)
         rd.ReadInt(v.BackgroundColor);
      END
   END Internalize;

PROCEDURE (v: View) Externalize (VAR wr: Stores.Writer);
   BEGIN
      wr.WriteVersion(maxVersion);
      Views.WriteView(wr, v.inner);   (* handle Views.Alien if necessary *)
      wr.WriteInt(v.BackgroundColor);
   END Externalize;

PROCEDURE (v: View) CopyFromModelView (source: Views.View; model: Models.Model);
   BEGIN
      WITH source: View DO
         v.BackgroundColor:=source.BackgroundColor;
         IF model = NIL THEN
            v.inner := Views.CopyOf(source.inner, Views.deep)
         ELSE
            v.inner := Views.CopyWithNewModel(source.inner, model)
         END
      END
   END CopyFromModelView;

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

PROCEDURE (v: View) InitContext (context: Models.Context);
   BEGIN
      v.InitContext^(context);
      v.inner.InitContext(context)   (* wrapper and wrapped view share the same context *)
   END InitContext;

PROCEDURE (v: View) Neutralize;
   BEGIN
      v.inner.Neutralize
   END Neutralize;

PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
   BEGIN
      Views.InstallFrame(f, v.inner, 0, 0, 0, TRUE);
   END Restore;

PROCEDURE (v: View) HandleCtrlMsg (f: Views.Frame; VAR msg: Controllers.Message; VAR focus: Views.View);
   BEGIN
      WITH msg:FindMsg DO
         IF v.inner=msg.v THEN
            msg.v:=v
         ELSE
            focus:=v.inner
         END
      ELSE
         focus := v.inner
      END;
   END HandleCtrlMsg;

PROCEDURE (v: View) HandleViewMsg (f:Views.Frame; VAR msg:Views.Message);
   BEGIN
      WITH msg: Views.ScrollClassMsg DO
         msg.allowBitmapScrolling := TRUE
      ELSE
      END
   END HandleViewMsg;

PROCEDURE (v: View) HandlePropMsg (VAR msg: Properties.Message);
   BEGIN
      Views.HandlePropMsg(v.inner, msg)
   END HandlePropMsg;

PROCEDURE (v: View) GetBackground (VAR color: Ports.Color);
   BEGIN
      color:=v.BackgroundColor
   END GetBackground;

PROCEDURE WrapView(v:Views.View): View;
   VAR
      w:View;
      replace: Controllers.ReplaceViewMsg;
   BEGIN
      ASSERT(v#NIL);
      ASSERT(~(v IS View));

      NEW(w);
      w.inner := v;
      Stores.Join(w, w.inner);
      replace.old := v;
      replace.new := w;
      Controllers.Forward(replace);
      RETURN w
   END WrapView;

PROCEDURE UnwrapView(v:View);
   VAR
      replace: Controllers.ReplaceViewMsg;
   BEGIN
      ASSERT(v#NIL);

      replace.old := v;
      replace.new := v.inner;
      Controllers.Forward(replace);
   END UnwrapView;

PROCEDURE FindWrapper (inner:Views.View): View;
   VAR
      find:FindMsg;
   BEGIN
      find.v:=inner;
      Controllers.Forward(find);
      IF find.v=inner THEN
         RETURN NIL
      ELSE
         RETURN find.v(View)
      END;
   END FindWrapper;

PROCEDURE GetCurrentView (): Views.View;
   BEGIN
      RETURN Controllers.FocusView()
   END GetCurrentView;

PROCEDURE SetBackgroundColor * ();
   VAR
      set:BOOLEAN;
      color:Ports.Color;
      v:View;
      FocusView:Views.View;
      script: Stores.Operation;
   BEGIN
      FocusView:=GetCurrentView();
      IF FocusView=NIL THEN
         RETURN
      END;
      
      v:=FindWrapper(FocusView);
      IF v#NIL THEN
         color:=v.BackgroundColor
      ELSE
         color:=Ports.defaultColor
      END;
      
      Dialog.GetColor(color,color,set);

      IF set THEN
         IF v=NIL THEN
            v:=WrapView(FocusView);
         END;
         v.BackgroundColor:=color;
         Views.Update(v,FALSE)
      END;
      
   END SetBackgroundColor;

PROCEDURE SetTransparentBackground * ();
   VAR
      FocusView:Views.View;
      v:View;
   BEGIN
      FocusView:=GetCurrentView();
      v:=FindWrapper(FocusView);
      IF v#NIL THEN
         UnwrapView(v);
      END;
   END SetTransparentBackground;

END MyWrapper.

Автор:  Info21 [ Пятница, 27 Ноябрь, 2009 01:14 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

В меню указывается тип объекта, для которого меню. Посмотрите менюшные документы, там всё очевидно.

Автор:  Илья Ермаков [ Пятница, 27 Ноябрь, 2009 01:18 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Когда пишете обёртку, надо быть внимательным с обработкой фокуса. Если всё нормально, то среда будет считать, что в фокусе именно внутреннее отображение - и меню будет вести себя, как положено.

Автор:  Евгений Темиргалеев [ Пятница, 27 Ноябрь, 2009 10:06 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

В Cpc есть пример: http://www.zinnamturm.eu/downloadsOS.ht ... ckgrounder
Цитата:
Set Background Colour in Views.

StdBackgrounder is a simple example of implementing a 'Wrapper'. It is used to add a background colour to arbitrary Views embedded into a Text Document.

Автор:  GameHunter [ Суббота, 28 Ноябрь, 2009 00:31 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

В StdBackgrounder'е та же проблема: при фокусе обёрнутого документа некоторые пункты меню гаснут.

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

Автор:  Евгений Темиргалеев [ Суббота, 28 Ноябрь, 2009 01:03 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

от стандартного примера ObxWrappers отличие есть :
Код:
   (* HandleModelMsg: framework performs message propagation *)
   (* HandleViewMsg: framework performs message propagation *)

может в этом дело

Автор:  Info21 [ Суббота, 28 Ноябрь, 2009 10:42 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Евгений Темиргалеев писал(а):
от стандартного примера ObxWrappers отличие есть :
Код:
   (* HandleModelMsg: framework performs message propagation *)
   (* HandleViewMsg: framework performs message propagation *)

может в этом дело
Кстати, механизм этих самых message propagations в документации ББ описан так, что может вызвать заворот мозгов.
У них там особый жаргон, меня ставили в тупик модальные конструкции, которые в принципе можно трактовать прямо противоположным образом. Хотя надо признать, что изложение довольно систематическое, только предварительного учебничка по жаргону нет :)

В общем, некоторого разжевывания этих механизмов пока не хватает.

Автор:  Иван Горячев [ Суббота, 28 Ноябрь, 2009 11:33 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Активность меню определяется через Controllers.PollOpsMsg. Причём в поле msg.type нужно возвращать имя абстрактного базового класса (обёртываемого объекта, надо полагать)

Автор:  GameHunter [ Вторник, 01 Декабрь, 2009 00:04 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Цитата:
Активность меню определяется через Controllers.PollOpsMsg. Причём в поле msg.type нужно возвращать имя абстрактного базового класса (обёртываемого объекта, надо полагать)

Не помогает.

Обнаружил, что все меню корректно работают, если вьюшка вложенная в документ. Вероятно, обёртка все сообщения отсылает правильно, но что-то не стыкуется на верхнем уровне документа...

Автор:  Иван Горячев [ Вторник, 01 Декабрь, 2009 02:47 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

GameHunter писал(а):
Не помогает.

Прошу прощения, послал Вас немножко не туда :? Краткое пояснение, как работает меню в ББ:

Вся работа с меню происходит в модуле HostMenus. Там нас интересуют процедуры: PrepareMenu, UpdateMenu и UpdateType и переменная type.

1. Связка UpdateMenu/UpdateType/type отвечает за динамическое формирование строки меню в зависимости от выбранной вьюшки (т.е. тех меню, у которых в файле Menus.odc указан ViewType). Общая схема такова:
UpdateType с помощью Controllers.PollOps посылает сообщение Controllers.PollOpsMsg, и по результату заполняет type, а затем UpdateMenu ориентируясь на полученный тип пересоздаёт что надо.

2. PrepareMenu отвечает за активность пунктов, галочки и прочую атрибутику отдельных пунктов. Делается это через StdDialog.CheckFilter, который вызывает guard прописанный в файле Menus.odc. Т.е. для каждого конкретного случая нужно смотреть как работает конкретный guard.

Вы указали неработающие пункты - Dev->Set...Mode. Guard для них - StdCmds.Set...ModeGuard, а интересует нас - GetMode. Он использует Views.HandlePropMsg с сообщением Containers.GetOpts.

Но! Посылается это сообщение только если у вас отображение-singleton или контейнер (т.е. расширение Containers.View). А вот разобраться, как именно оно находит этот singleton меня не хватило - там пяток модулей с хуками и фабриками друг на друга, и проследить цепочку вызовов - :shock: Но думаю проблема в том, что Ваша обёртка - Views.View, а не Containers.View.

Автор:  Иван Горячев [ Вторник, 01 Декабрь, 2009 10:54 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Кстати, ещё один момент: приведённый модуль неправильно ищет view для обёртывания - если я в документ вставлю коммандер, выделю его (F6) - и попытаюсь обернуть - обернётся документ, а не коммандер. Потому как должно быть:
Код:
PROCEDURE GetCurrentView (): Views.View;
VAR c : Containers.Controller;
BEGIN
  c := Containers.Focus();
  IF (c # NIL) & (c.Singleton() # NIL) THEN (*возвращаем именно выбранный view *)
    RETURN c.Singleton()
  ELSE (* можно вернуть и текущий контейнер. Но можно и не возвращать, дабы не плодить поведений по умолчанию *)
    RETURN Controllers.FocusView()
  END
END GetCurrentView;

Автор:  GameHunter [ Среда, 02 Декабрь, 2009 12:22 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Цитата:
Но думаю проблема в том, что Ваша обёртка - Views.View, а не Containers.View.

Вы правы, охрана этих пунктов меню рассчитана на Containers.View. Получается, что, вообще говоря, универсальную "прозрачную" обётрку создать не возможно, т.к. для этого она должна иметь тип обёртываемой вьюшки :(

Автор:  Иван Горячев [ Среда, 02 Декабрь, 2009 14:21 ]
Заголовок сообщения:  Re: Элементы меню для документа в обёртке

Почему? Берём в качестве базы Containers.View - и вперёд. Поскольку в контейнерах по определению может лежать всё что угодно, должно получиться. Только возни больше.

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

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/