Model view controller Rebol VID MVC:如果Rebol不';不支持自定义事件?
假设我有一个模型/控制器,有两个同时的视频格式。如果Rebol不支持自定义事件,我将如何更新指向同一模型的两个视图?我继续进行,并从实现属性编辑器MVC中获得了乐趣 此示例允许您直接从GUI动态创建模型和视图,因此它非常适合显示实际运行的系统 当多个视图编辑同一数据时,您将看到它们保持同步。多个模型可能每个都有多个视图 这只是一个例子,展示了在REBOL中构建MVC模式是多么容易。事实上,REBOL中的许多构造在精神上已经是MVC了,即使它们没有明确地作为MVC进行营销Model view controller Rebol VID MVC:如果Rebol不';不支持自定义事件?,model-view-controller,rebol,Model View Controller,Rebol,假设我有一个模型/控制器,有两个同时的视频格式。如果Rebol不支持自定义事件,我将如何更新指向同一模型的两个视图?我继续进行,并从实现属性编辑器MVC中获得了乐趣 此示例允许您直接从GUI动态创建模型和视图,因此它非常适合显示实际运行的系统 当多个视图编辑同一数据时,您将看到它们保持同步。多个模型可能每个都有多个视图 这只是一个例子,展示了在REBOL中构建MVC模式是多么容易。事实上,REBOL中的许多构造在精神上已经是MVC了,即使它们没有明确地作为MVC进行营销 rebol [
rebol [
title: "MVC pattern example"
purpose: {
shows an example of a raw MVC pattern in REBOL
the views can create new models and new views, showing interaction
between separate models, views and the controler.
}
]
model!: context [
data: none
views: []
modify: func [label value][
set in data label value
]
propagate: func [
/only label
/local view
][
foreach view views [
either only [
view/refresh/only label
][
view/refresh
]
]
]
]
view!: context [
controller: none ; our controller
model: none ; our model
label: none ; what label in data does this view manipulate?
gui: [
across
space 2x10
style separator box 275x3 edge [size: 1x1 effect: 'ibevel color: (white * .75)]
]
lbl: none ; gui face
fld: none ; gui face
refresh: func [/only label][
; GENERATE the gui if its not been built for this view yet.
if block? gui [
gui: copy/deep gui
; add a button for each item of data in the model, clicking on them changes
; what the field edits.
foreach item words-of model/data [
append gui compose/deep bind/copy [
btn (to-string item) [
print "^/---"
label: (to-lit-word item)
probe label
refresh
]
] self
]
; we must bind because the block is being used in new objects created dynamically.
; if we don't bind the blocks, they stay bound to the class... important detail.
append gui copy/deep bind/copy [
return
separator
return
lbl: h1 200 (to-string label)
return
fld: field [controller/modify model label face/text]
btn "randomize" [controller/randomize model label]
return
pad 0x10
separator
return
pad 160x0
btn "new view" [controller/new-view (model)]
btn "new model" [controller/new-model]
btn "close" [unview/only gui]
] self
gui: view/new layout gui
]
; refresh the gui, when its already built (including on first view)
if any [
none? label
label = self/label
] [
probe model/data
probe self/label
fld/text: copy get in model/data self/label
lbl/text: copy to-string self/label
show fld
show lbl
]
]
]
controller!: context [
models: []
; this just describes how the models should be built,
; it could be a hard-coded in new-model()
model-data: [sid: "0" name: "unknown" occupation: "unknown"]
new-model: func [/local model view prev-model prev-view][
unless empty? models [prev-model: last models]
append models model: make model! [data: context model-data ]
view: new-view model
if prev-model [
; tweak window position which is a bit screwed up in rebol
prev-view: last prev-model/views
view/gui/offset/x: view/gui/offset/x + system/view/no-resize-border/x
view/gui/offset/y: prev-view/gui/offset/y + prev-view/gui/size/y + system/view/no-resize-border/y 8
show view/gui
]
model
]
new-view: func [model /local view prev-view][
probe model/data
if not empty? model/views [
probe length? model/views
prev-view: last model/views
]
append model/views view: make view! compose [
model: (model)
label: (to-lit-word first words-of model/data)
controller: (self) ; here self is the controller, since we are composing
; the value within a controller function
]
view/refresh
if prev-view [
; tweak window position which is a bit screwed up in rebol
view/gui/offset/x: prev-view/gui/offset/x + prev-view/gui/size/x + system/view/no-resize-border/x
view/gui/offset/y: prev-view/gui/offset/y - system/view/title-size/y - system/view/no-resize-border/y - 2
show view/gui
]
view
]
; general case "set" operation
modify: func [model label value][
model/modify label value
model/propagate/only label
]
; just an example controler method
randomize: func [
model
label
][
modify model label random copy get in model/data label
]
]
ids: make controller! []
ids/new-model
do-events
我继续进行,并从实现属性编辑器MVC中获得了乐趣 此示例允许您直接从GUI动态创建模型和视图,因此它非常适合显示实际运行的系统 当多个视图编辑同一数据时,您将看到它们保持同步。多个模型可能每个都有多个视图 这只是一个例子,展示了在REBOL中构建MVC模式是多么容易。事实上,REBOL中的许多构造在精神上已经是MVC了,即使它们没有明确地作为MVC进行营销
rebol [
title: "MVC pattern example"
purpose: {
shows an example of a raw MVC pattern in REBOL
the views can create new models and new views, showing interaction
between separate models, views and the controler.
}
]
model!: context [
data: none
views: []
modify: func [label value][
set in data label value
]
propagate: func [
/only label
/local view
][
foreach view views [
either only [
view/refresh/only label
][
view/refresh
]
]
]
]
view!: context [
controller: none ; our controller
model: none ; our model
label: none ; what label in data does this view manipulate?
gui: [
across
space 2x10
style separator box 275x3 edge [size: 1x1 effect: 'ibevel color: (white * .75)]
]
lbl: none ; gui face
fld: none ; gui face
refresh: func [/only label][
; GENERATE the gui if its not been built for this view yet.
if block? gui [
gui: copy/deep gui
; add a button for each item of data in the model, clicking on them changes
; what the field edits.
foreach item words-of model/data [
append gui compose/deep bind/copy [
btn (to-string item) [
print "^/---"
label: (to-lit-word item)
probe label
refresh
]
] self
]
; we must bind because the block is being used in new objects created dynamically.
; if we don't bind the blocks, they stay bound to the class... important detail.
append gui copy/deep bind/copy [
return
separator
return
lbl: h1 200 (to-string label)
return
fld: field [controller/modify model label face/text]
btn "randomize" [controller/randomize model label]
return
pad 0x10
separator
return
pad 160x0
btn "new view" [controller/new-view (model)]
btn "new model" [controller/new-model]
btn "close" [unview/only gui]
] self
gui: view/new layout gui
]
; refresh the gui, when its already built (including on first view)
if any [
none? label
label = self/label
] [
probe model/data
probe self/label
fld/text: copy get in model/data self/label
lbl/text: copy to-string self/label
show fld
show lbl
]
]
]
controller!: context [
models: []
; this just describes how the models should be built,
; it could be a hard-coded in new-model()
model-data: [sid: "0" name: "unknown" occupation: "unknown"]
new-model: func [/local model view prev-model prev-view][
unless empty? models [prev-model: last models]
append models model: make model! [data: context model-data ]
view: new-view model
if prev-model [
; tweak window position which is a bit screwed up in rebol
prev-view: last prev-model/views
view/gui/offset/x: view/gui/offset/x + system/view/no-resize-border/x
view/gui/offset/y: prev-view/gui/offset/y + prev-view/gui/size/y + system/view/no-resize-border/y 8
show view/gui
]
model
]
new-view: func [model /local view prev-view][
probe model/data
if not empty? model/views [
probe length? model/views
prev-view: last model/views
]
append model/views view: make view! compose [
model: (model)
label: (to-lit-word first words-of model/data)
controller: (self) ; here self is the controller, since we are composing
; the value within a controller function
]
view/refresh
if prev-view [
; tweak window position which is a bit screwed up in rebol
view/gui/offset/x: prev-view/gui/offset/x + prev-view/gui/size/x + system/view/no-resize-border/x
view/gui/offset/y: prev-view/gui/offset/y - system/view/title-size/y - system/view/no-resize-border/y - 2
show view/gui
]
view
]
; general case "set" operation
modify: func [model label value][
model/modify label value
model/propagate/only label
]
; just an example controler method
randomize: func [
model
label
][
modify model label random copy get in model/data label
]
]
ids: make controller! []
ids/new-model
do-events
如果您在这里提供一个代码示例,它将非常有用。基本上说“这是我知道的有用的东西,好吧,很好”,然后“但这是一个阻碍我实现我想要的东西…”我还没有在尝试之前等待建议,但ok会尝试以下方法:)实现MVC的方法太多了,除非你告诉我们你是如何实现的,否则答案是不可能的。不是太多:你有一个模型,你想在模型字段每次更改时自动更新2个视图,您如何在rebol中传播/广播该更改?当然,模型必须是与视图不同的对象:目的是分离实体,rebol倾向于创建单个文件并混合所有内容。我使用liquid Dataflow模块在原子级别上实现MVC类型的约束。但这意味着您的数据和GUI必须液化,玻璃就是这样。使用liquid还意味着您可以改变编程模式(从命令式到数据流),因此这可能是一个相当大的方法变化。基本上说“这是我知道的有用的东西,好吧,很好”,然后“但这是一个阻碍我实现我想要的东西…”我还没有在尝试之前等待建议,但ok会尝试以下方法:)实现MVC的方法太多了,除非你告诉我们你是如何实现的,否则答案是不可能的。不是太多:你有一个模型,你想在模型字段每次更改时自动更新2个视图,您如何在rebol中传播/广播该更改?当然,模型必须是与视图不同的对象:目的是分离实体,rebol倾向于创建单个文件并混合所有内容。我使用liquid Dataflow模块在原子级别上实现MVC类型的约束。但这意味着您的数据和GUI必须液化,玻璃就是这样。使用liquid还意味着改变编程模式(从命令式到数据流),因此这可能是一个相当大的方法变化。