Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: Demo of Model-View-Controller design
name
code content
s.boot; ( ~model = NodeProxy.control(s, 1).source_(440); ~makeView = { |model| var view = Slider(nil, Rect(800, 200, 200, 40)) // user action: change the model .action_({ |view| model.source = \freq.asSpec.map(view.value); }) .value_(\freq.asSpec.unmap(model.source)), // 'args' depends on who is sending the notification // NodeProxy sends an array, where the new 'source' is args[0] controller = SimpleController(model).put(\source, { |obj, what, args| defer { view.value = \freq.asSpec.unmap(args[0]) }; }); view.onClose = { controller.remove }; view.front }; ~sound = NodeProxy.audio(s, 2).source_({ SinOsc.ar(~model.kr(1), 0, 0.1).dup }).play; ) a = ~makeView.(~model); b = ~makeView.(~model); // 2nd view-controller, auto-synced! ~model.source = 220; ~model.dependants // 2 controllers // close windows ~model.dependants // empty ~model.clear; ~sound.clear;
code description
This question comes up often: What is the best way to structure GUI code. IMO, Model-View-Controller (when done correctly) gives you the most flexibility while avoiding common bugs. But it's hard to wrap your head around it first. So, here's a quick example using NodeProxies. - Model: This is the thing that is actually doing the work. Here, it's a control proxy representing a frequency value. When something interesting happens in the model (e.g., the frequency changes), it should broadcast a notification (in SC, using the '.changed' method). NodeProxy already does this internally (which is why I'm using it for this example!). - View: The GUI display -- a Slider, in this case. The view knows who its model is, and should respond to user action by updating the model. - Controller: An object that receives notifications from the model and communicates with the view. This SimpleController object is looking for '\source' notifications, and changes the view's displayed value. Benefits: You can make as many views as you want, on the same model, and their separate controllers all receive the notifications and keep everything in sync *without* having to manage exponentially-increasing connections. You can set the model programmatically and all views automatically update. Drawbacks: The model needs to send notifications. Sometimes it's hard to anticipate which notifications will be needed. Bugs can be hard to track down (but when each component is doing its job correctly, it ends up being easier to maintain).
use markdown for formating
category tags
comma separated, i.g. "wild, siren" (do not enter default SC class names, please)
ancestor(s)
comma separated identificators, i.g. "1-C,1-1,1-4M,1-x"
Private?
the code will be accessible by direct url and not visible in public activity
signup to submit public code without captcha
comment of change