OberonCore https://forum.oberoncore.ru/ |
|
Лог на форме https://forum.oberoncore.ru/viewtopic.php?f=24&t=355 |
Страница 1 из 1 |
Автор: | Cardinal [ Воскресенье, 24 Декабрь, 2006 11:31 ] |
Заголовок сообщения: | Лог на форме |
Хочу создать текстовой лог, который лежит на форме, открытой как OpenToolDialog. Код: MODULE TestControls;
IMPORT Dialog, Controls, TextModels, Views, Models, Stores, Properties, Controllers; TYPE Log* = RECORD END; CustomLog = POINTER TO RECORD (Controls.Control) model: TextModels.Model; view: Views.View END; LogMsg = RECORD (Models.Message) string: Dialog.String END; Context = POINTER TO RECORD (Models.Context) w, h: INTEGER; view, base: Views.View; END; VAR log*: Log; (** Log **) PROCEDURE (VAR l: Log) Add* (IN s: ARRAY OF CHAR), NEW; VAR msg: LogMsg; BEGIN msg.string := s$; Views.Omnicast(msg) END Add; (** Context **) PROCEDURE (c: Context) GetSize(OUT w, h: INTEGER); BEGIN w := c.w; h := c.h END GetSize; PROCEDURE (c: Context) SetSize(w, h: INTEGER); VAR msg: Properties.SizePref; BEGIN msg.h := h; msg.w := w; msg.fixedH := FALSE; msg.fixedW := FALSE; Views.HandlePropMsg(c.view, msg); c.w := msg.w; c.h := msg.h END SetSize; PROCEDURE (c: Context) ThisModel(): Models.Model; BEGIN RETURN NIL END ThisModel; PROCEDURE (c: Context) Normalize(): BOOLEAN; BEGIN RETURN FALSE END Normalize; PROCEDURE NewContext(view: Views.View; base: Views.View): Context; VAR context: Context; msg: Properties.SizePref; BEGIN ASSERT(view # NIL, 20); ASSERT(base # NIL, 21); msg.w := Views.undefined; msg.h := Views.undefined; msg.fixedW := FALSE; msg.fixedH := FALSE; Views.HandlePropMsg(view, msg); IF view.context = NIL THEN NEW ( context ); context.w := msg.w; context.h := msg.h; context.view := view; context.base := base; view.InitContext( context ); Stores.Join(view, base) END; RETURN context END NewContext; (** CustomLog **) PROCEDURE PaintLog (c: CustomLog; f: Views.Frame); VAR w, h: INTEGER; BEGIN c.context.GetSize(w, h); f.DrawRect(0, 0, w, h, f.dot, Ports.black); IF c.model # NIL THEN IF c.view # NIL THEN c.view.context.SetSize(w, h); Views.InstallFrame(f, c.view, 0, 0, 0, TRUE); END END; END PaintLog; PROCEDURE (c: CustomLog) Externalize2 (VAR wr: Stores.Writer); BEGIN wr.WriteVersion(maxVersion); wr.WriteStore(c.model) END Externalize2; PROCEDURE (c: CustomLog) Internalize2 (VAR rd: Stores.Reader); VAR version: INTEGER; store: Stores.Store; context: Context; BEGIN rd.ReadVersion(minVersion, maxVersion, version); rd.ReadStore(store); WITH store: TextModels.Model DO c.model := store; c.view := TextViews.dir.New(c.model); context := NewContext(c.view, c); (*MtScrollers.AddScrollerOn(c.view)*) END; END Internalize2; PROCEDURE (c: CustomLog) Restore (f: Views.Frame; l, t, r, b: INTEGER); BEGIN PaintLog(c, f) END Restore; PROCEDURE (c: CustomLog) HandleCtrlMsg2 (f: Views.Frame; VAR msg: Controllers.Message; VAR focus: Views.View); BEGIN IF ~c.disabled & c.item.Valid() THEN focus := c.view END; END HandleCtrlMsg2; PROCEDURE (c: CustomLog) HandleModelMsg (VAR msg: Models.Message); VAR form: TextMappers.Formatter; BEGIN WITH msg: LogMsg DO form.ConnectTo(c.model); form.WriteString(msg.string$); form.WriteLn; Views.Update(c, Views.keepFrames) ELSE (* ignore other messages *) END END HandleModelMsg; PROCEDURE (c: CustomLog) HandlePropMsg2 (VAR msg: Properties.Message); BEGIN WITH msg: Properties.FocusPref DO IF ~c.disabled & ~c.readOnly THEN msg.setFocus := TRUE END | msg: Properties.SizePref DO IF (msg.w = Views.undefined) OR (msg.h = Views.undefined) THEN msg.w := 50 * Ports.mm; msg.h := 50 * Ports.mm END ELSE END END HandlePropMsg2; PROCEDURE (c: CustomLog) CheckLink (VAR ok: BOOLEAN); VAR mod, name: Meta.Name; v: Meta.Item; control: REAL; BEGIN ok := FALSE; IF (c.item.typ = Meta.recTyp) THEN c.item.GetTypeName(mod, name); ok := TRUE END END CheckLink; PROCEDURE (c: CustomLog) Update (f: Views.Frame; op, from, to: INTEGER); BEGIN PaintLog(c, f) END Update; PROCEDURE NewLog* (p: Controls.Prop): Views.View; VAR c: CustomLog; context: Context; BEGIN NEW(c); c.model := TextModels.dir.New(); c.view := TextViews.dir.New(c.model); context := NewContext(c.view, c); (*MtScrollers.AddScrollerOn(c.view);*) Controls.OpenLink(c, p); RETURN c END NewLog; PROCEDURE DepositLog*; VAR p: Controls.Prop; BEGIN NEW(p); p.link := "TestControls.log"; p.label := ""; p.guard := ""; p.notifier := ""; Views.Deposit(NewLog(p)) END DepositLog; Такой способ работает, сообщения добавляются. Но при добавлении скроллера (программного MtScrollers или в режиме разработки - через меню Tools - Add Scroller) - мой контрол становится белым и ничего не отображается или вылетают трапы в процедуре Restore на вызов c.view.context.SetSize(..) - c.view.context отчего-то равен NIL. Подскажите корректный способ добавления скроллера, кто знает, или другой способ создания лога. |
Автор: | Илья Ермаков [ Воскресенье, 24 Декабрь, 2006 20:26 ] |
Заголовок сообщения: | |
К сожалению, подробно сейчас разбираться не могу. Навскидку: не совсем понятен смысл наследования от Control, да и вообще смысл создания нетекстового лога. По существу проблемы: 1) смущает SetSize, косвенно вызываемый из Restore - насколько я помню, этого делать нельзя, это может вести к сложным рекурсивным петлям обновления экрана; 2) прокрутка в ББ может делаться двух видов: а) отображение, вложенное в скроллер, имеет большой размер, а уже скроллер его прокручивает. Это просто, т.к. отображению не нужно заботиться о прокрутке вообще; б) для отображений со сложным содержанием (например, тексты) - размер отображения всегда равен размеру скроллера, показ нужного места обеспечивает само отображение, обрабатывая в HandleCtrlMsg сообщения Controllers.PollSectionMsg и SetSectionMsg. Можно реализовать такую логику. Был уже подробный пример - см. ветку viewtopic.php?t=241. Однако я сейчас не уверен, что у Controls нет уже своей обработки этих сообщений, а Вы наследуетесь от него - проверьте! |
Автор: | Cardinal [ Воскресенье, 24 Декабрь, 2006 21:40 ] |
Заголовок сообщения: | |
Лог мне нужен как раз текстовой. Цель - записывать в этот лог свои строки, и сохранить этот лог. Наследование от Controls.Control чтобы использовать интерактор и соотвествующий ему элемент управления (по аналогии с Dialog.List -> ListBox) и заносить сообщения в лог: Код: log.Add ("my message")
К тому же (наследуясь от Controls.Control) я получаю доступ к своему интерактору через Meta, а от Views.View - не пробовал ещё, возможно пробовать надо будет как в ObxButtons. Метод c.view.context.SetSize(...) работает у меня в разных вьюшках без проблем. Хотя мне не нравится вызывать его каждый раз в Restore, только другого способа я пока не знаю (да и не пробовал - проблем не возникало); можно ли (и корректно ли) это делать, например, в HandlePropMsg? А Controllers.PollSectionMsg действительно не приходит в HandleCtrlMsg2. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |