On Sat, Apr 29, 2017 at 4:20 AM, Rob Rothwell <r.j.rothwell@gmail.com> wrote:
Hi Peter,
Thanks again for the advice. I've reduced my number of infinite loops and crashes by creating copies of pertinent classes and using them for testing, but I have quickly learned to save my image after inserting a halt anywhere!
Its a bit of a trick to learn to change the wheels on the car while its still driving, but also very useful. Try using #haltOnce instead. cheers -ben
The parallel Spec implementation conversation is interesting too, but unfortunately I don't understand enough to participate very much yet.
However, I have discovered by creating new ComposableModel, WindowModel, and MorphicWindowAdapter classes that even the SpecInterpreter itself is hard-wired to use Morphic.
If you take a look at
WindowModel>>privateAdapterFromModel: aModel withSpec: aSpec "apparently when looking at the implementation, it does not return a widget but an adapter so it should be called adapter :)" self halt. ^ SpecInterpreter private_buildWidgetFor: self withSpec: aSpec.
You see from the correct comment that an adapter is created during this operation, which I think (I'm not that far yet) comes from
SpecInterpreter class>>defaultBindings ^ MorphicAdapterBindings new
In other words, I think that regardless of WindowModel class>>adapterName (and presumably all other "Model" classes, the actual adapter used is at present determined by the SpecInterpreter via MorphicAdapterBindings>> initializeBindings.
You can set the bindings on the class side, but I currently don't see a way to say "open this spec using these bindings." In other words, something like:
MyApplication new openWithSpecAndBindings: MorphicAdapterBindings.
or simply
MyApplication openAsMorphicSpec, MyApplication openAsCocoaSpec, etc...
It's starting to make some sense at a high level, though. Eventually I'll find a spot where I can create a CocoaWindow and start figuring out the minimum interface requirements!
Take care,
Rob
On Fri, Apr 28, 2017 at 6:13 AM, Peter Uhnak <i.uhnak@gmail.com> wrote:
Hi Rob,
I need to find a good starting point because you can't poke at the existing code too much since even the debugger is built with Spec!
I don't know what Pharo you are on, but this is not the case. Debugger itself is based on Glamour (there used to be SpecDebugger, but it is no longer used).
What is blowing up on you is the predebugger window, which is in Spec. You can disable this in your settings or by calling
GTGenericStackDebugger alwaysOpenFullDebugger: true
this will skip the debugger.
But keep in mind that other tools might be using spec too (like the Browser window that opens when you are listing senders/implementors.
overriding the #windowClass (or whatever the name was) is a good start.
(also FML because apparently I've deleted my image with my spec changes by accident -_-)
Peter
It's pretty exciting, though, because it feels like all the right pieces are there and a lot of this could mostly be "just work" once I get
going.
Thanks again,
Rob
On Thu, Apr 27, 2017 at 6:04 PM, Peter Uhnak <i.uhnak@gmail.com> wrote:
Hi Rob,
I guess the best resource at the moment is to just look at existing adapters.
But here are some thoughts to get you started:
(Spec) ComposableModel has as its widget (Spec) Adapter Adapter has as its widget the actual visual component, which currently means Morphic.
The simplest example: LabelModel
1. model to adapter
LabelModel is adapted by MorphicLabelAdapter:
you can see on the class side in method `defaultSpec`. There is only `LabelAdapter` there because there is some extra
mapping for
some classes, but you can specify directly the class of the Adapter, so the following would work just as well:
LabelModel class>>defaultSpec <spec>
^ #(MorphicLabelAdapter adapt: #(model))
LabelModel -> LabelAdapter direct event propagation (pushing changes)
in Model world you can call changed:with: to execute code on the Adapter, e.g.
self changed: #emphasis: with: {emphasis}
which in turn will call the #emphasis: method on the LabelAdapter.
LabelModel -> LabelAdapter events (pulling changes)
preferred alternative is to do the opposite; properties of models are often held in ValueHolders, which can be observed on ValueChange, so the Adapter can register to event change and react on itself;
you can see this best in MorphicTabAdapter (but you will see that TabAdapter looks a bit different from the rest, because I was experimenting with cleaning up Adapters...)
2. adapter to morphic
Every adapter implements #buildWidget method that returns a Morphic Object. Typically the adapter registers itself as the model of the adapter (so adapter's model is Spec, and Morphic's model is the adapter). This depends a lot on the API of morphic. (in TabAdapter I'm overriding adapt: so there's no buildWidget, and it is in #buildWidgetWith:).
It is all kinds of messy, but if you have other widgets then it will be a good test how well Spec can handle it... or rather we'll see how it can be improved...
Peter
On Thu, Apr 27, 2017 at 05:10:39PM -0400, Rob Rothwell wrote:
Hello,
I have recently been lucky enough to get the Cocoa portion of Mars working on Pharo 5.0. While there are some issues, it has a wonderful set of examples that allowed me create new Cocoa classes and delegate methods and see a straightforward path to learning how to use Coco widgets from Pharo.
I'd like to do that by creating appropriate Spec adapters, but unfortunately the new Spec booklet wasn't designed for that!
Can anyone give me any insight into creating (and using) a new Spec adapter? Maybe just some high level steps to help me orient my investigation into how Spec works?
Thank you,
Rob