OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 29 Март, 2024 10:03

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




Начать новую тему Ответить на тему  [ Сообщений: 13 ] 
Автор Сообщение
СообщениеДобавлено: Пятница, 27 Ноябрь, 2009 01:00 

Зарегистрирован: Вторник, 22 Май, 2007 15:38
Сообщения: 220
Откуда: Питер
Уважаемые специалисты,

Я изучаю ББ, пытаюсь написать обёртку для изменения фона документов.
Проблема такая: когда вьюшка документа обёрнута,
некоторые пункты меню, активные без обёртки, не активны.
Например, 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.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 27 Ноябрь, 2009 01:14 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 8500
Откуда: Троицк, Москва
В меню указывается тип объекта, для которого меню. Посмотрите менюшные документы, там всё очевидно.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 27 Ноябрь, 2009 01:18 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Когда пишете обёртку, надо быть внимательным с обработкой фокуса. Если всё нормально, то среда будет считать, что в фокусе именно внутреннее отображение - и меню будет вести себя, как положено.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 27 Ноябрь, 2009 10:06 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
В 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.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 28 Ноябрь, 2009 00:31 

Зарегистрирован: Вторник, 22 Май, 2007 15:38
Сообщения: 220
Откуда: Питер
В StdBackgrounder'е та же проблема: при фокусе обёрнутого документа некоторые пункты меню гаснут.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 28 Ноябрь, 2009 01:03 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
от стандартного примера ObxWrappers отличие есть :
Код:
   (* HandleModelMsg: framework performs message propagation *)
   (* HandleViewMsg: framework performs message propagation *)

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 28 Ноябрь, 2009 10:42 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 8500
Откуда: Троицк, Москва
Евгений Темиргалеев писал(а):
от стандартного примера ObxWrappers отличие есть :
Код:
   (* HandleModelMsg: framework performs message propagation *)
   (* HandleViewMsg: framework performs message propagation *)

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

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 28 Ноябрь, 2009 11:33 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Активность меню определяется через Controllers.PollOpsMsg. Причём в поле msg.type нужно возвращать имя абстрактного базового класса (обёртываемого объекта, надо полагать)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 01 Декабрь, 2009 00:04 

Зарегистрирован: Вторник, 22 Май, 2007 15:38
Сообщения: 220
Откуда: Питер
Цитата:
Активность меню определяется через Controllers.PollOpsMsg. Причём в поле msg.type нужно возвращать имя абстрактного базового класса (обёртываемого объекта, надо полагать)

Не помогает.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 01 Декабрь, 2009 02:47 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
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 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Кстати, ещё один момент: приведённый модуль неправильно ищет 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;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 02 Декабрь, 2009 12:22 

Зарегистрирован: Вторник, 22 Май, 2007 15:38
Сообщения: 220
Откуда: Питер
Цитата:
Но думаю проблема в том, что Ваша обёртка - Views.View, а не Containers.View.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 02 Декабрь, 2009 14:21 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Почему? Берём в качестве базы Containers.View - и вперёд. Поскольку в контейнерах по определению может лежать всё что угодно, должно получиться. Только возни больше.

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


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

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


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

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


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

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