Коллеги, я взялся делать реализацию FormControllers.Controller, и обнаружил, что FormControllers.Focus() не "видит" никаких реализаций контроллеров, кроме стандартных.
Чтобы найти контроллер в фокусе, она посылает сообщение PollFocusMsg:
Код:
PROCEDURE Focus* (): Controller;
VAR msg: PollFocusMsg;
BEGIN
msg.c := NIL;
Controllers.Forward(msg);
RETURN msg.c
END Focus;
И на это сообщение откликается стандартный контроллер:
Код:
PROCEDURE (c: StdController) HandleCtrlMsg (f: Views.Frame; VAR msg: Views.CtrlMessage;
VAR focus: Views.View);
BEGIN
WITH msg: PollFocusMsg DO
c.HandleCtrlMsg^(f, msg, focus);
msg.c := c
ELSE
c.HandleCtrlMsg^(f, msg, focus)
END
END HandleCtrlMsg;
И вот беда: PollFocusMsg не экспортируется. Поэтому никакая другая реализация контроллера не может откликнуться на него, и потому невидима для Focus().
Замечу, что TextControllers.Focus() реализована иначе, не задействуя сообщения напрямую:
Код:
PROCEDURE (*TextControllers.*)Focus* (): Controller;
VAR v: Views.View; c: Containers.Controller;
BEGIN
v := Controllers.FocusView();
IF (v # NIL) & (v IS TextViews.View) THEN
c := v(TextViews.View).ThisController();
IF (c # NIL) & (c IS Controller) THEN RETURN c(Controller)
ELSE RETURN NIL
END
ELSE RETURN NIL
END
END Focus;
Предлагаю исправить эту ошибку, вариантов несколько:
1) Экспортировать PollFocusMsg из FormControllers, либо
2) Перенести отклик на PollFocusMsg из скрытого FormControllers.StdController.HandleCtrlMsg в FormControllers.Controllers.HandleCtrlMsg. При этом придется сделать его EXTENSIBLE и вызывать из расширений, либо делать нерасширимым и вводить HandleCtrlMsg2. Громоздко.
3) Переделать вообще реализацию по типу TextControllers. В этом варианте вообще никакие интерфейсы затрагивать не придется.