Spec: Binding widgets how to

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
28 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Spec: Binding widgets how to

Offray
Hi,

I'm starting to migrate my grafoscopio interface from only GT to Spec-Glamorous. I have kind of a working layout as you can see:



and now I want to bind the different widgets so when I select a tree node I can show/edit its title and contents. I have read the Spec documentation on how to do this [1] and the ListSelectionModel code from Spec-Examples, but seems I'm missing something.

[1] http://spec.st/docs/interactions/

So, I have a

GrafoscopioGUI>>initializePresenter
    tree whenSelectedItemChanged: [ self updateHeader ]

and

GrafoscopioGUI>>updateHeader
    "update the displayed text associated to the header"
   
    ^ nodeHeader text: tree selectedItem.


but when I move on the tree, nothing happens in the header panel at the bottom.

What I'm missing?

Thanks,

Offray
Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

webwarrior
Try #whenHighlightedItemChanged: method.

I remember that distinction between selection/highlight is not very clear in TreeModel.
Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Offray
Hi,

I had tried that before and didn't work. Passing information between
widgets and back in this spec interface seems my stop point now... If
someone could help me with some kind of minimalist example that uses
treeModel, that would be greatly appreciated.

Cheers,

Offray

On 26/11/15 12:47, webwarrior wrote:

> Try #whenHighlightedItemChanged: method.
>
> I remember that distinction between selection/highlight is not very clear in
> TreeModel.
>
>
>
> --
> View this message in context: http://forum.world.st/Spec-Binding-widgets-how-to-tp4863742p4863757.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Nicolai Hess-3-2


2015-11-26 19:36 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Hi,

I had tried that before and didn't work. Passing information between widgets and back in this spec interface seems my stop point now... If someone could help me with some kind of minimalist example that uses treeModel, that would be greatly appreciated.

Find attached a minimal example. (I use Morph and its subclasses for generating some tree data, these are just names, renaming a node does not rename the class :))

You can listen on tree node selection by registering with #whenSelectedChanged, on the TreeNode(!)

"create the node"
t :=  TreeNodeModel new
        content: aClass name;
        hasChildren: [ aClass subclasses notEmpty ];
        children: [ subItems ifNil:[subItems:=aClass subclasses collect: [ :s | self buildNodeFor: s ] ]];
        yourself.

"listen on selection"
t whenSelectedChanged: [ :bool | bool ifTrue:[self field text: t content] ].

this will change the text field content with the content of the node (the default label).

Changing the label node *Morph* on accepting the text field text is somehow impossible or difficult.
I would have expected that Spec would create a MorphicTreeNodeAdapter that represents some Morph, for which the adapter would update/change the state, if you change
the TreeNodeModel content.
Instead, it creates some strange SpecTreeNodeModel. And the only way to update the NodeLabel and make this change visible is to
rebuild the whole tree:

tree roots: tree roots.

Yes, I did not find another way.

Luckily MorphTreeMorph is smart enough to remember the selection and path expansion state, so this works quite well.

 

Cheers,

Offray


On 26/11/15 12:47, webwarrior wrote:
Try #whenHighlightedItemChanged: method.

I remember that distinction between selection/highlight is not very clear in
TreeModel.



--
View this message in context: http://forum.world.st/Spec-Binding-widgets-how-to-tp4863742p4863757.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.






Tree-TextField-Demo-NicolaiHess.2.mcz (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Offray
Thanks Nicolai for your minimalist example. Only until now I have time to test it (sorry), but I get some "MessageNotUnderstood: SpecTreeNodeModel>>layoutFrame:" when I run this:

=================
| aClass subItems |
aClass := RTObject.
subItems := RTObject subclasses.
"create the node"
t :=  TreeNodeModel new
        content: aClass name;
        hasChildren: [ aClass subclasses notEmpty ];
        children: [ subItems ifNil:[subItems:=aClass subclasses collect: [ :s | self buildNodeFor: s ] ]];
        yourself.
"listen on selection"
t whenSelectedChanged: [ :bool | bool ifTrue:[self field text: t content] ].
t openWithSpec
=================

There is any way to run a minimal GUI with a tree using your example? I'm still missing a key concept on how to use spec and binding between widgets.

Thanks,

Offray

On 29/11/15 13:51, Nicolai Hess wrote:


2015-11-26 19:36 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Hi,

I had tried that before and didn't work. Passing information between widgets and back in this spec interface seems my stop point now... If someone could help me with some kind of minimalist example that uses treeModel, that would be greatly appreciated.

Find attached a minimal example. (I use Morph and its subclasses for generating some tree data, these are just names, renaming a node does not rename the class :))

You can listen on tree node selection by registering with #whenSelectedChanged, on the TreeNode(!)

"create the node"
t :=  TreeNodeModel new
        content: aClass name;
        hasChildren: [ aClass subclasses notEmpty ];
        children: [ subItems ifNil:[subItems:=aClass subclasses collect: [ :s | self buildNodeFor: s ] ]];
        yourself.

"listen on selection"
t whenSelectedChanged: [ :bool | bool ifTrue:[self field text: t content] ].

this will change the text field content with the content of the node (the default label).

Changing the label node *Morph* on accepting the text field text is somehow impossible or difficult.
I would have expected that Spec would create a MorphicTreeNodeAdapter that represents some Morph, for which the adapter would update/change the state, if you change
the TreeNodeModel content.
Instead, it creates some strange SpecTreeNodeModel. And the only way to update the NodeLabel and make this change visible is to
rebuild the whole tree:

tree roots: tree roots.

Yes, I did not find another way.

Luckily MorphTreeMorph is smart enough to remember the selection and path expansion state, so this works quite well.

 

Cheers,

Offray


On 26/11/15 12:47, webwarrior wrote:
Try #whenHighlightedItemChanged: method.

I remember that distinction between selection/highlight is not very clear in
TreeModel.



--
View this message in context: http://forum.world.st/Spec-Binding-widgets-how-to-tp4863742p4863757.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.






Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Nicolai Hess-3-2


2015-12-23 16:50 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Thanks Nicolai for your minimalist example. Only until now I have time to test it (sorry), but I get some "MessageNotUnderstood: SpecTreeNodeModel>>layoutFrame:" when I run this:

=================
| aClass subItems |
aClass := RTObject.
subItems := RTObject subclasses.
"create the node"
t :=  TreeNodeModel new
        content: aClass name;
        hasChildren: [ aClass subclasses notEmpty ];
        children: [ subItems ifNil:[subItems:=aClass subclasses collect: [ :s | self buildNodeFor: s ] ]];
        yourself.
"listen on selection"
t whenSelectedChanged: [ :bool | bool ifTrue:[self field text: t content] ].
t openWithSpec
=================

The children block codee only works as part of the class I defined with the method buildNodeFor:
( it calls "self buildNodeFor:")



 

There is any way to run a minimal GUI with a tree using your example? I'm still missing a key concept on how to use spec and binding between widgets.

what is missing ? this is a minimal gui with a tree component.
 

Thanks,

Offray


On 29/11/15 13:51, Nicolai Hess wrote:


2015-11-26 19:36 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email][hidden email]>:
Hi,

I had tried that before and didn't work. Passing information between widgets and back in this spec interface seems my stop point now... If someone could help me with some kind of minimalist example that uses treeModel, that would be greatly appreciated.

Find attached a minimal example. (I use Morph and its subclasses for generating some tree data, these are just names, renaming a node does not rename the class :))

You can listen on tree node selection by registering with #whenSelectedChanged, on the TreeNode(!)

"create the node"
t :=  TreeNodeModel new
        content: aClass name;
        hasChildren: [ aClass subclasses notEmpty ];
        children: [ subItems ifNil:[subItems:=aClass subclasses collect: [ :s | self buildNodeFor: s ] ]];
        yourself.

"listen on selection"
t whenSelectedChanged: [ :bool | bool ifTrue:[self field text: t content] ].

this will change the text field content with the content of the node (the default label).

Changing the label node *Morph* on accepting the text field text is somehow impossible or difficult.
I would have expected that Spec would create a MorphicTreeNodeAdapter that represents some Morph, for which the adapter would update/change the state, if you change
the TreeNodeModel content.
Instead, it creates some strange SpecTreeNodeModel. And the only way to update the NodeLabel and make this change visible is to
rebuild the whole tree:

tree roots: tree roots.

Yes, I did not find another way.

Luckily MorphTreeMorph is smart enough to remember the selection and path expansion state, so this works quite well.

 

Cheers,

Offray


On 26/11/15 12:47, webwarrior wrote:
Try #whenHighlightedItemChanged: method.

I remember that distinction between selection/highlight is not very clear in
TreeModel.



--
View this message in context: http://forum.world.st/Spec-Binding-widgets-how-to-tp4863742p4863757.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.







Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Offray
Hi,

On 03/01/16 08:45, Nicolai Hess wrote:

 

There is any way to run a minimal GUI with a tree using your example? I'm still missing a key concept on how to use spec and binding between widgets.

what is missing ? this is a minimal gui with a tree component.
 

Ohh, what is missing is not in the example, but in my understanding on how to use/start it. I would expect for something like "example openWithSpec" to start deconstructing it, but I'm still lost about it. I will be working on it today and tomorrow to see if I can come with better questions.

Cheers,

Offray
Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Nicolai Hess-3-2


2016-01-03 23:52 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Hi,

On 03/01/16 08:45, Nicolai Hess wrote:

 

There is any way to run a minimal GUI with a tree using your example? I'm still missing a key concept on how to use spec and binding between widgets.

what is missing ? this is a minimal gui with a tree component.
 

Ohh, what is missing is not in the example, but in my understanding on how to use/start it. I would expect for something like "example openWithSpec" to start deconstructing it, but I'm still lost about it. I will be working on it today and tomorrow to see if I can come with better questions.

Ok, for this example you can just start it with:

TreeDemo new openWithSpec

It opens a window with two panes, the upper pane shows a tree with some nodes (subclasses of class Morph)
The lower pane shows the text(name) of the selected node. You can change and accept (cmd+s) the text in the
lower pane, which will update the name of the tree node.

 

Cheers,

Offray

Reply | Threaded
Open this post in threaded view
|

Re: Spec: Binding widgets how to

Offray
Thanks again Nicolai! I will start from here :-).

Offray

On 03/01/16 18:20, Nicolai Hess wrote:


2016-01-03 23:52 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Hi,

On 03/01/16 08:45, Nicolai Hess wrote:

 

There is any way to run a minimal GUI with a tree using your example? I'm still missing a key concept on how to use spec and binding between widgets.

what is missing ? this is a minimal gui with a tree component.
 

Ohh, what is missing is not in the example, but in my understanding on how to use/start it. I would expect for something like "example openWithSpec" to start deconstructing it, but I'm still lost about it. I will be working on it today and tomorrow to see if I can come with better questions.

Ok, for this example you can just start it with:

TreeDemo new openWithSpec

It opens a window with two panes, the upper pane shows a tree with some nodes (subclasses of class Morph)
The lower pane shows the text(name) of the selected node. You can change and accept (cmd+s) the text in the
lower pane, which will update the name of the tree node.

 

Cheers,

Offray


Reply | Threaded
Open this post in threaded view
|

Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
Hi,

Thanks to NIcolai's help with his minimalist example I'm on track now and finally I have started to understand better the events in Spec. My problem was in the incorrect use of whenHighlightedItemChanged. Now the code its working fine and I can browse the tree and see the related contents on the respective UI panels (see attached screenshot and code at [*] at the end to see how was solved).

Now I'm facing another issue: As you can see in the attached screenshot the UI has four parts: A tool bar above all, a tree with the node title (called node header) at left and a bigger panel at right with node contents (called node body). I would like to make the node body behave in a similar way as in my previous non-Spec interface, so it can react differently according to the node tags. If the node is tagged as code, it will become a playground with node contents inside such playground. If node is not tagged it will be a text like now (this is already working). So my questions are:

1) How can I populate a Spec-Glamour playground with a particular text code?
2) How can I initializeWidgets with some kind of conditions depending on the kind of selection I have done on the tree? At this moment my initializeWidgets look like this:

==[2a]===========
GrafoscopioGUI>>initializeWidgets
    "Buils graphical interface elements"

    windowMainMenu := self windowMainMenu.
    tree := self tree.
    nodeHeader := self newTextInput.
    nodeBody :=
        tree selectedItem notNil
            ifTrue: [ self updateBody ]
            ifFalse: [nodeBody := self newText].
    windowMainMenu applyTo: self.
    self focusOrder
        add: windowMainMenu;
        add: tree;
        add: nodeHeader;
        add: nodeBody.
================

and my updataBody (where I think that this conditional behavior could be looks like this:

==[2b]===========
GrafoscopioGUI>>updateBody
    "update the displayed content associated to the body of a node"
   
    (tree selectedItem content tags = 'código')
        ifTrue: [
            ^ nodeBody text: 'I should be playground because I am tagged as ', tree selectedItem content tags
        ]
        ifFalse: [
            ^ nodeBody text: tree selectedItem content body
        ]
================

So, more precisely, what I need to put in the ifTrue part of [2b] to make the interface to return a playground with pre-populated code? (is it the proper place?)

Finally, here is the code that made the tree update properly, just for the curious ones.

==[*]============
GrafoscopioGUI>>tree
    | notebook |
    notebook := GrafoscopioNode new becomeDefaultTestTree.
    tree := TreeModel new.
    tree
        roots: notebook children;
        childrenBlock: [:node | node children];
        displayBlock: [:node | node title ].
    tree whenHighlightedItemChanged: 
         [tree selectedItem notNil
            ifTrue: [
                self updateHeader.
                self updateBody.
            ]
         ].
    ^ tree
================

Cheers,

Offray


On 03/01/16 18:33, Offray Vladimir Luna Cárdenas wrote:
Thanks again Nicolai! I will start from here :-).

Offray

On 03/01/16 18:20, Nicolai Hess wrote:


2016-01-03 23:52 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Hi,

On 03/01/16 08:45, Nicolai Hess wrote:

 

There is any way to run a minimal GUI with a tree using your example? I'm still missing a key concept on how to use spec and binding between widgets.

what is missing ? this is a minimal gui with a tree component.
 

Ohh, what is missing is not in the example, but in my understanding on how to use/start it. I would expect for something like "example openWithSpec" to start deconstructing it, but I'm still lost about it. I will be working on it today and tomorrow to see if I can come with better questions.

Ok, for this example you can just start it with:

TreeDemo new openWithSpec

It opens a window with two panes, the upper pane shows a tree with some nodes (subclasses of class Morph)
The lower pane shows the text(name) of the selected node. You can change and accept (cmd+s) the text in the
lower pane, which will update the name of the tree node.

 

Cheers,

Offray




tree-node-details-working.png (23K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

jfabry
Hola,

it looks like what you want here is covered by dynamic spec. Have a look at the dynamic spec section in the Spec booklet (work in progress) https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/Spec/ I think that it will answer your question.

On Jan 7, 2016, at 22:36, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

 How can I initializeWidgets with some kind of conditions depending on the kind of selection I have done on the tree? 


---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile

Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
Thanks Johan,

This seems what I'm looking for.

I running now the examples at the dynamic spec section and I have found an error in Script 1.41: Setting up the sub widgets (pg 24 of current version) in the first line, where it says " view label text: 'Packages:'." it should be " view label label: 'Packages:'." There is any place where I can report and/or correct such errors?

Cheers,

Offray

On 08/01/16 06:21, Johan Fabry wrote:
Hola,

it looks like what you want here is covered by dynamic spec. Have a look at the dynamic spec section in the Spec booklet (work in progress) https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/Spec/ I think that it will answer your question.

On Jan 7, 2016, at 22:36, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

 How can I initializeWidgets with some kind of conditions depending on the kind of selection I have done on the tree? 


---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

jfabry

Consider the error as reported! I should work on this text soon so I will fix it. If you find any more errors feel free to send me a mail.

On Jan 8, 2016, at 12:43, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Thanks Johan,

This seems what I'm looking for.

I running now the examples at the dynamic spec section and I have found an error in Script 1.41: Setting up the sub widgets (pg 24 of current version) in the first line, where it says " view label text: 'Packages:'." it should be " view label label: 'Packages:'." There is any place where I can report and/or correct such errors?

Cheers,

Offray

On 08/01/16 06:21, Johan Fabry wrote:
Hola,

it looks like what you want here is covered by dynamic spec. Have a look at the dynamic spec section in the Spec booklet (work in progress) https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/Spec/ I think that it will answer your question.

On Jan 7, 2016, at 22:36, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

 How can I initializeWidgets with some kind of conditions depending on the kind of selection I have done on the tree? 


---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile





---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile

Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
Hi Johan,

I have not found more errors on the booklet, but I think that I'm not getting the explanation of dynamic spec. Consider this code:


==============================
GrafoscopioGUI Class>>exampleBootstrapDynamicUI
    "Starting from an example UI from the Spec-Glamour, to customize towards the grafoscopio
    UI and get some ideas"

    |notebook leftUpperPanel leftPanel treeBrowser |
   
    "Creating a notebook-tree with dummy data"
    notebook := GrafoscopioNode new becomeDefaultTestTree.
   
    "Defining the tree roots part"
    leftUpperPanel := DynamicComposableModel new.
    leftUpperPanel instantiateModels: #(tree TreeModel).
    leftUpperPanel tree
        roots: notebook children;
        childrenBlock: [:node | node children ];
        displayBlock: [:node | node title ].
    leftUpperPanel layout: (SpecLayout composed
        add: #tree;
        yourself).
    "to debug upto here uncomment the next line, and comment all other 'openWithSpec' ones"
    "leftUpperPanel openWithSpec."
   
    "Integrating the previous tree with the node header and creating the body according to
    the tags on the node"
    leftPanel := DynamicComposableModel new.
    leftPanel assign: leftUpperPanel to: #roots.
    leftPanel instantiateModels: #(header TextInputFieldModel).   
    treeBrowser := DynamicComposableModel new.
    leftUpperPanel tree
        whenSelectedItemChanged: [:node |
            node
                ifNil:[
                    leftPanel header text: ''.
                    treeBrowser instantiateModels: #(body TextModel).
                    Transcript show: 'Nada que mostrar', String cr]
                ifNotNil: [
                    leftPanel header text: (leftUpperPanel tree selectedItem content header).
                    leftUpperPanel tree selectedItem content tags = 'código'
                        ifTrue: [
                            treeBrowser instantiateModels: #(body GlamourPresentationModel).
                            Transcript show: 'I am code', String cr.
                            Transcript show: treeBrowser body asString, String cr.
                        ]
                        ifFalse: [
                            treeBrowser instantiateModels: #(body TextModel).
                            treeBrowser body text: (leftUpperPanel tree selectedItem content body).
                            Transcript show: 'I am NOT code', String cr.
                            Transcript show: treeBrowser body asString, String cr.
                        ]
                ]
        ].
    leftPanel layout:
        (SpecLayout composed
            newColumn: [:column |
                    column
                        add: #roots;
                        add: #header height: 35];
            yourself).
   
    "Integrating the previous tree with node body content"
    treeBrowser assign: leftPanel to: #leftTree.
    treeBrowser layout:
        (SpecLayout composed
            newRow: [:r | r add: #leftTree; add: #body ];
            yourself
        ).
    treeBrowser openWithSpec.
==============================

I can get the interface shown here:



and when I move between nodes in the upper left tree the correspondent name in the lower left input box changes accordingly, but nothing else happens on the right side panel. I have put the definition of the type and contents of such panel inside a whenSelectionChanged block, as you can see in the previous code, because I think that right panel should change according to the type of node that is selected, but this doesn't work. The debug info that I send to a transcript show that #body becomes a GlamourPresentationModel or a TextModel depending on which node I'm selecting. I don't know what I'm doing wrong or how this dynamic spec is supposed to behave... well, dynamically, and accordingly making layout components to change on the fly.

How can I make the right panel change to become a GlamourPresentationModel or a TextModel in Spec-Glamour?

Thanks,

Offray


On 08/01/16 12:10, Johan Fabry wrote:

Consider the error as reported! I should work on this text soon so I will fix it. If you find any more errors feel free to send me a mail.

On Jan 8, 2016, at 12:43, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Thanks Johan,

This seems what I'm looking for.

I running now the examples at the dynamic spec section and I have found an error in Script 1.41: Setting up the sub widgets (pg 24 of current version) in the first line, where it says " view label text: 'Packages:'." it should be " view label label: 'Packages:'." There is any place where I can report and/or correct such errors?

Cheers,

Offray

On 08/01/16 06:21, Johan Fabry wrote:
Hola,

it looks like what you want here is covered by dynamic spec. Have a look at the dynamic spec section in the Spec booklet (work in progress) https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/Spec/ I think that it will answer your question.

On Jan 7, 2016, at 22:36, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

 How can I initializeWidgets with some kind of conditions depending on the kind of selection I have done on the tree? 


---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile





---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
Hi,

Lets try something simpler. Consider this code:

=============================
| data m1 m2 |

data := { 'first' -> 'I\"m just text' . 'second' -> 'ProfStef openPharoZenWorkspace'} asOrderedDictionary.

m1 := DynamicComposableModel new.
m1 instantiateModels: #(list ListModel).
m1 list items: (data keys).
m1 layout:
    (SpecLayout composed
        add: #list;
        yourself).

m2 := DynamicComposableModel new.
m2 instantiateModels: #(right TextModel).
m2 assign: m1 to: #left.
m1 list
    whenSelectedItemChanged: [:item |
        item
            ifNil: [
                m2 instantiateModels: #(right TextModel).
                m2 right text: ''
            ]
            ifNotNil: [
                item = 'first'
                    ifTrue: [
                        m2 instantiateModels: #(right TextModel).
                        Transcript show: m2 right asString, String cr
                    ].
                item = 'second'
                    ifTrue: [
                        m2 instantiateModels: #(right GlamourPresentationModel).
                        Transcript show: m2 right asString, String cr].
            ]
    ].

m2 layout:
    (SpecLayout composed
        newRow: [:r | r add: #left; add: #right];
        yourself).
m2 openWithSpec

=============================

Shouldn't be #right dynamically defined according to the values of 'item' and be replaced on the m2 layout? The transcript show that anytime I change the selection in this small spec interface, m2 right is changed. Is it not what I'm putting in the right side of the interface with the line which says:  "newRow: [:r | r add: #left; add: #right];"

How can I made spec in this small example show the respective value in the dictionary when the key value is "first" inside a TextModel and the respective value in the dictionary when the key value is "second" inside a GlamourPresentationModel?

Cheers,

Offray

On 08/01/16 19:06, Offray Vladimir Luna Cárdenas wrote:
Hi Johan,

I have not found more errors on the booklet, but I think that I'm not getting the explanation of dynamic spec. Consider this code:


==============================
GrafoscopioGUI Class>>exampleBootstrapDynamicUI
    "Starting from an example UI from the Spec-Glamour, to customize towards the grafoscopio
    UI and get some ideas"

    |notebook leftUpperPanel leftPanel treeBrowser |
   
    "Creating a notebook-tree with dummy data"
    notebook := GrafoscopioNode new becomeDefaultTestTree.
   
    "Defining the tree roots part"
    leftUpperPanel := DynamicComposableModel new.
    leftUpperPanel instantiateModels: #(tree TreeModel).
    leftUpperPanel tree
        roots: notebook children;
        childrenBlock: [:node | node children ];
        displayBlock: [:node | node title ].
    leftUpperPanel layout: (SpecLayout composed
        add: #tree;
        yourself).
    "to debug upto here uncomment the next line, and comment all other 'openWithSpec' ones"
    "leftUpperPanel openWithSpec."
   
    "Integrating the previous tree with the node header and creating the body according to
    the tags on the node"
    leftPanel := DynamicComposableModel new.
    leftPanel assign: leftUpperPanel to: #roots.
    leftPanel instantiateModels: #(header TextInputFieldModel).   
    treeBrowser := DynamicComposableModel new.
    leftUpperPanel tree
        whenSelectedItemChanged: [:node |
            node
                ifNil:[
                    leftPanel header text: ''.
                    treeBrowser instantiateModels: #(body TextModel).
                    Transcript show: 'Nada que mostrar', String cr]
                ifNotNil: [
                    leftPanel header text: (leftUpperPanel tree selectedItem content header).
                    leftUpperPanel tree selectedItem content tags = 'código'
                        ifTrue: [
                            treeBrowser instantiateModels: #(body GlamourPresentationModel).
                            Transcript show: 'I am code', String cr.
                            Transcript show: treeBrowser body asString, String cr.
                        ]
                        ifFalse: [
                            treeBrowser instantiateModels: #(body TextModel).
                            treeBrowser body text: (leftUpperPanel tree selectedItem content body).
                            Transcript show: 'I am NOT code', String cr.
                            Transcript show: treeBrowser body asString, String cr.
                        ]
                ]
        ].
    leftPanel layout:
        (SpecLayout composed
            newColumn: [:column |
                    column
                        add: #roots;
                        add: #header height: 35];
            yourself).
   
    "Integrating the previous tree with node body content"
    treeBrowser assign: leftPanel to: #leftTree.
    treeBrowser layout:
        (SpecLayout composed
            newRow: [:r | r add: #leftTree; add: #body ];
            yourself
        ).
    treeBrowser openWithSpec.
==============================

I can get the interface shown here:



and when I move between nodes in the upper left tree the correspondent name in the lower left input box changes accordingly, but nothing else happens on the right side panel. I have put the definition of the type and contents of such panel inside a whenSelectionChanged block, as you can see in the previous code, because I think that right panel should change according to the type of node that is selected, but this doesn't work. The debug info that I send to a transcript show that #body becomes a GlamourPresentationModel or a TextModel depending on which node I'm selecting. I don't know what I'm doing wrong or how this dynamic spec is supposed to behave... well, dynamically, and accordingly making layout components to change on the fly.

How can I make the right panel change to become a GlamourPresentationModel or a TextModel in Spec-Glamour?

Thanks,

Offray


On 08/01/16 12:10, Johan Fabry wrote:

Consider the error as reported! I should work on this text soon so I will fix it. If you find any more errors feel free to send me a mail.

On Jan 8, 2016, at 12:43, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Thanks Johan,

This seems what I'm looking for.

I running now the examples at the dynamic spec section and I have found an error in Script 1.41: Setting up the sub widgets (pg 24 of current version) in the first line, where it says " view label text: 'Packages:'." it should be " view label label: 'Packages:'." There is any place where I can report and/or correct such errors?

Cheers,

Offray

On 08/01/16 06:21, Johan Fabry wrote:
Hola,

it looks like what you want here is covered by dynamic spec. Have a look at the dynamic spec section in the Spec booklet (work in progress) https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/Spec/ I think that it will answer your question.

On Jan 7, 2016, at 22:36, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

 How can I initializeWidgets with some kind of conditions depending on the kind of selection I have done on the tree? 


---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile





---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile



Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

jfabry
Sorry for the lateness and short reply but I’m involved in a bunch of other things that are taking almost all of my time ...

From what I understand and what I can see in your code, you want to modify a widget when the UI is open. However you never trigger the rebuilding of the window. For example, see the Spec docs that I sent, where in 9.1 there is code that calls buildWithSpecLayout: . 

Actually, I am not sure you need to subclass DynamicComposableModel since the number of widgets never changes. You can use a normal ComposableModel subclass and use what is detailed in 9.1 to change the layout between the two options you want to have (a TextModel or a GlamourPresentationModel).

On Jan 8, 2016, at 23:07, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Shouldn't be #right dynamically defined according to the values of 'item' and be replaced on the m2 layout? 



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile

Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
Thanks Johan I will follow from there and report back as soon as I have some results.

Cheers,

Offray

On 10/01/16 13:39, Johan Fabry wrote:
Sorry for the lateness and short reply but I’m involved in a bunch of other things that are taking almost all of my time ...

From what I understand and what I can see in your code, you want to modify a widget when the UI is open. However you never trigger the rebuilding of the window. For example, see the Spec docs that I sent, where in 9.1 there is code that calls buildWithSpecLayout: . 

Actually, I am not sure you need to subclass DynamicComposableModel since the number of widgets never changes. You can use a normal ComposableModel subclass and use what is detailed in 9.1 to change the layout between the two options you want to have (a TextModel or a GlamourPresentationModel).

On Jan 8, 2016, at 23:07, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Shouldn't be #right dynamically defined according to the values of 'item' and be replaced on the m2 layout? 



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
In reply to this post by jfabry
Hi,

I've reading the code at [1] but I'm still having problems understanding the dynamic spec. I have created a small dictionary and populated with data, then created the accessors and initializePresenter, initializeWidgets and rebuildWithdCodeLayout and rebuildWithTextLayout, as you can see on the following snippets, but nothing happens despite the debugging Transcript is showing me that the content subwidget has the proper model, but is not rebuild in the GUI.

Any help is, as always, very much appreciated.

[1] https://github.com/spec-framework/documentation/blob/master/output/book.md#rebuildDynamically

----------------------
DynamicDict>>initializeWidgets

    | data |
    data := { 'first' -> 'I\"m just text' . 'second' -> 'ProfStef openPharoZenWorkspace'} asOrderedDictionary.
    list := self newList.
    list items: data keys.
    content := self newText.
    self focusOrder
        add: list;
        add: content.
----------------------
DynamicDict>>initializePresenter
    list whenSelectedItemChanged: [:item |
        item = 'first'
            ifTrue: [ self rebuildWithTextLayout ].
        item = 'second'
            ifTrue: [ self rebuildWithCodeLayout ].       
    ]
----------------------
DynamicDict>>rebuildWithCodeLayout
    | newLayout |
   
    content := self instantiate: GlamourPresentationModel.
    newLayout := SpecLayout composed
        newRow: [:row |
            row
                add: #list right: 0.7;
                add: #content left: 0.3];
        yourself.
    self needRebuild: true.
    content needRebuild: true.
    Transcript show: 'código + ', self content asString, String cr.
    self buildWithSpecLayout: newLayout.
----------------------
DynamicDict>>rebuildWithTextLayout
    | newLayout |
   
    content := self newText.
    newLayout := SpecLayout composed
        newRow: [:row |
            row
                add: #list right: 0.7;
                add: #content left: 0.3];
        yourself.
    self needRebuild: false.
    list needRebuild: false.
    content needRebuild: true.
    Transcript show: 'texto + ', self content asString, String cr..
    self buildWithSpecLayout: newLayout.
----------------------

Cheers,

Offray

On 10/01/16 13:39, Johan Fabry wrote:
Sorry for the lateness and short reply but I’m involved in a bunch of other things that are taking almost all of my time ...

From what I understand and what I can see in your code, you want to modify a widget when the UI is open. However you never trigger the rebuilding of the window. For example, see the Spec docs that I sent, where in 9.1 there is code that calls buildWithSpecLayout: . 

Actually, I am not sure you need to subclass DynamicComposableModel since the number of widgets never changes. You can use a normal ComposableModel subclass and use what is detailed in 9.1 to change the layout between the two options you want to have (a TextModel or a GlamourPresentationModel).

On Jan 8, 2016, at 23:07, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Shouldn't be #right dynamically defined according to the values of 'item' and be replaced on the m2 layout? 



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Nicolai Hess-3-2


2016-01-13 23:07 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:
Hi,

I've reading the code at [1] but I'm still having problems understanding the dynamic spec. I have created a small dictionary and populated with data, then created the accessors and initializePresenter, initializeWidgets and rebuildWithdCodeLayout and rebuildWithTextLayout, as you can see on the following snippets, but nothing happens despite the debugging Transcript is showing me that the content subwidget has the proper model, but is not rebuild in the GUI.

Any help is, as always, very much appreciated.

Hi Offray,

I think you have to call
    self needRebuild: false.
in both rebuild... methods.
Otherwise the all "inner"-widgets are rebuild:

 

[1] https://github.com/spec-framework/documentation/blob/master/output/book.md#rebuildDynamically

----------------------
DynamicDict>>initializeWidgets

    | data |
    data := { 'first' -> 'I\"m just text' . 'second' -> 'ProfStef openPharoZenWorkspace'} asOrderedDictionary.
    list := self newList.
    list items: data keys.
    content := self newText.
    self focusOrder
        add: list;
        add: content.
----------------------
DynamicDict>>initializePresenter
    list whenSelectedItemChanged: [:item |
        item = 'first'
            ifTrue: [ self rebuildWithTextLayout ].
        item = 'second'
            ifTrue: [ self rebuildWithCodeLayout ].       
    ]
----------------------
DynamicDict>>rebuildWithCodeLayout
    | newLayout |
   
    content := self instantiate: GlamourPresentationModel.
    newLayout := SpecLayout composed
        newRow: [:row |
            row
                add: #list right: 0.7;
                add: #content left: 0.3];
        yourself.
    self needRebuild: true.
    content needRebuild: true.
    Transcript show: 'código + ', self content asString, String cr.
    self buildWithSpecLayout: newLayout.
----------------------
DynamicDict>>rebuildWithTextLayout
    | newLayout |
   
    content := self newText.
    newLayout := SpecLayout composed
        newRow: [:row |
            row
                add: #list right: 0.7;
                add: #content left: 0.3];
        yourself.
    self needRebuild: false.
    list needRebuild: false.
    content needRebuild: true.
    Transcript show: 'texto + ', self content asString, String cr..
    self buildWithSpecLayout: newLayout.
----------------------

Cheers,

Offray

On 10/01/16 13:39, Johan Fabry wrote:
Sorry for the lateness and short reply but I’m involved in a bunch of other things that are taking almost all of my time ...

From what I understand and what I can see in your code, you want to modify a widget when the UI is open. However you never trigger the rebuilding of the window. For example, see the Spec docs that I sent, where in 9.1 there is code that calls buildWithSpecLayout: . 

Actually, I am not sure you need to subclass DynamicComposableModel since the number of widgets never changes. You can use a normal ComposableModel subclass and use what is detailed in 9.1 to change the layout between the two options you want to have (a TextModel or a GlamourPresentationModel).

On Jan 8, 2016, at 23:07, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Shouldn't be #right dynamically defined according to the values of 'item' and be replaced on the m2 layout? 



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile



Reply | Threaded
Open this post in threaded view
|

Re: Spec: Populating a playground with a particular content (was Re: Spec: Binding widgets how to)

Offray
Hi Nicolai,

That was the issue. Now it's working! I was trying to test different combinations to see why UI updating was not happening but I got the variations wrong (one true, another false, instead of both false :-) ).

The next step I'm working on in populating the GTPlayPage with some particular content. In my previous interface I made something like this:

-[1]---------------------
GrafoscopioBrowser>>panelAsCodeFor: aNode
    "Shows an interactive playground for Smalltalk code in a node body"

    browser := GLMTabulator new.
    browser title: 'Código'.
    browser column: #code.
    browser transmit
        to: #code;
        transformed: [ GTPlayPage new content: aNode body ];
        andShow: [ :a | a custom: GTPlayground new ].
    browser sendToOutside: #nodeBody from: #code -> #text.
    ^ browser.
------------------------

In this one I tried some variation of GlamourPresentationModel>>glmPres that let the user predefine a content for the GTPlayPage like this:

-[2]----------------------
glmPresWithContent: aString
    glmPres isNil ifTrue:[
        glmPres := GTPlayground new startOn:  (GTPlayPage new content: aString)].
    ^glmPres
---------------------------

but if I try running the interface with this I get: "MessageNotUnderstood: GlamourPresentationModel>>content:", so I think that something more is needed to create Playgrounds in the Spec-Glamour that are pre-populated with content.

How can I create a playground inside a Spec-Glamour interface that is already populated with a given content?

Thanks,

Offray

On 14/01/16 03:56, Nicolai Hess wrote:


2016-01-13 23:07 GMT+01:00 Offray Vladimir Luna Cárdenas <[hidden email]>:ui insp presentationClass: GTInspector startOn: 42.
Hi,

I've reading the code at [1] but I'm still having problems understanding the dynamic spec. I have created a small dictionary and populated with data, then created the accessors and initializePresenter, initializeWidgets and rebuildWithdCodeLayout and rebuildWithTextLayout, as you can see on the following snippets, but nothing happens despite the debugging Transcript is showing me that the content subwidget has the proper model, but is not rebuild in the GUI.

Any help is, as always, very much appreciated.

Hi Offray,

I think you have to call
    self needRebuild: false.
in both rebuild... methods.
Otherwise the all "inner"-widgets are rebuild:

 

[1] https://github.com/spec-framework/documentation/blob/master/output/book.md#rebuildDynamically

----------------------
DynamicDict>>initializeWidgets

    | data |
    data := { 'first' -> 'I\"m just text' . 'second' -> 'ProfStef openPharoZenWorkspace'} asOrderedDictionary.
    list := self newList.
    list items: data keys.
    content := self newText.
    self focusOrder
        add: list;
        add: content.
----------------------
DynamicDict>>initializePresenter
    list whenSelectedItemChanged: [:item |
        item = 'first'
            ifTrue: [ self rebuildWithTextLayout ].
        item = 'second'
            ifTrue: [ self rebuildWithCodeLayout ].       
    ]
----------------------
DynamicDict>>rebuildWithCodeLayout
    | newLayout |
   
    content := self instantiate: GlamourPresentationModel.
    newLayout := SpecLayout composed
        newRow: [:row |
            row
                add: #list right: 0.7;
                add: #content left: 0.3];
        yourself.
    self needRebuild: true.
    content needRebuild: true.
    Transcript show: 'código + ', self content asString, String cr.
    self buildWithSpecLayout: newLayout.
----------------------
DynamicDict>>rebuildWithTextLayout
    | newLayout |
   
    content := self newText.
    newLayout := SpecLayout composed
        newRow: [:row |
            row
                add: #list right: 0.7;
                add: #content left: 0.3];
        yourself.
    self needRebuild: false.
    list needRebuild: false.
    content needRebuild: true.
    Transcript show: 'texto + ', self content asString, String cr..
    self buildWithSpecLayout: newLayout.
----------------------

Cheers,

Offray

On 10/01/16 13:39, Johan Fabry wrote:
Sorry for the lateness and short reply but I’m involved in a bunch of other things that are taking almost all of my time ...

From what I understand and what I can see in your code, you want to modify a widget when the UI is open. However you never trigger the rebuilding of the window. For example, see the Spec docs that I sent, where in 9.1 there is code that calls buildWithSpecLayout: . 

Actually, I am not sure you need to subclass DynamicComposableModel since the number of widgets never changes. You can use a normal ComposableModel subclass and use what is detailed in 9.1 to change the layout between the two options you want to have (a TextModel or a GlamourPresentationModel).

On Jan 8, 2016, at 23:07, Offray Vladimir Luna Cárdenas <[hidden email]> wrote:

Shouldn't be #right dynamically defined according to the values of 'item' and be replaced on the m2 layout? 



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile




12