using tree morphs

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

using tree morphs

Alexis Parseghian
I've been playing with MorphTree et al. for the past few days, trying
to understand how they work. Reading the example code in
Morphic-MorphTreeWidget-Examples helped. I've also been trying to
figure out the Settings Browser, but this one I have a hard time following :(

Anyway, I think I've got the basics now : I instantiate a
MorphTreeMorph when building my window in an subclass of a
MorphTreeModel. The contents of my model's list get wrapped in the
appropriate MorphTreeNodeModel subclasses.

I can get the tree to display *what* I want. My problem is with the
*how* ; more specifically, how to get the columns right.

* the first column always displays correctly, with or without an
expander (and in the latter case, expanded or not).
* the following columns have the text overlapping their left-side
resizer by about half a character.
* subsequent columns display off their vertical boundaries (to the
right), seemingly depending on the length of the preceeding column.
Same as if there were no columns but just morphs abutted to one
another. Manually resizing the previous column to contain the longest
text gets me back to the previous case (half a char too much to the
left). In other words, if I'm guessing right, the column clips its
contents /visually/, but not in relation to their /reported width/.

I'm pretty sure there's something really basic I've missed in the
layout, but I can't figure it out from the example code nor the
classes' protocols.

Any hints ?

Thanks.

My code:

* the root list is a collection of associations 'string' -> article instance
* I'm building a view with the category (expandable) in the first
column. Once expanded, it shows the article's properties in columns.

CategoriesAndArticlesTree(MorphTreeModel)>>buildTree
       | treeMorph |
       treeMorph := (self treeMorphClass on: self)
               columns: {
                       MorphTreeColumn new rowMorphGetSelector:
#categoryOrAuthor.
                       MorphTreeColumn new
                               rowMorphGetSelector: #title;
                               headerButtonLabel: 'Title' font: nil.
                       MorphTreeColumn new rowMorphGetSelector: #issue.
                       MorphTreeColumn new rowMorphGetSelector: #foo
                }.
       treeMorph
               hResizing: #spaceFill; vResizing: #spaceFill;
               withHLines: true;
               makeLastColumnUnbounded;
               resizerWidth: 1.
       ^ (treeMorph buildContents )
CategoriesAndArticlesTree>>rootNodeClassFromItem: anItem
       ^ CategoriesTreeNode

CategoriesTreeNode(MorphTreeNodeModel)>>categoryOrAuthor
       ^ self theme builder newLabel: item key
CategoriesTreeNode>>childNodeClassFromItem: anItem
       ^ ArticlesTreeNode
CategoriesTreeNode>>childrenItems
       ^ item value
the other column-related selectors are implemented and return a nil.

ArticlesTreeNode(MorphTreeNodeModel) implements the column-related
selectors by returning the appropriate article property wrapped in a
label.
ArticlesTreeNode>>categoryOrAuthor
       ^ self theme builder newLabel: item author
ArticlesTreeNode>>foo
       ^ self theme builder newLabel: 'foo'

Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

S Krish
Pay close attention to the example for
Class  PackageTreeExample

   it uses: method #rootNodeClassFromItem: to display its children
derived from #rootItems

 It picks up each of the node to display through: thereafter from the
various node classes it uses: All Nodes class should be a subclass of
PackageAbstractNodeExample

   #childNodeClassFromItem: and #childrenItems

 It is a beautiful nearly perfect tree morph, I have every used across
all UI from VC++/ VW/ VA / Java..

  study the abstract super class.. a bit and debug through the example
a bit more..


On 3/6/12, Alexis Parseghian <[hidden email]> wrote:

> I've been playing with MorphTree et al. for the past few days, trying
> to understand how they work. Reading the example code in
> Morphic-MorphTreeWidget-Examples helped. I've also been trying to
> figure out the Settings Browser, but this one I have a hard time following
> :(
>
> Anyway, I think I've got the basics now : I instantiate a
> MorphTreeMorph when building my window in an subclass of a
> MorphTreeModel. The contents of my model's list get wrapped in the
> appropriate MorphTreeNodeModel subclasses.
>
> I can get the tree to display *what* I want. My problem is with the
> *how* ; more specifically, how to get the columns right.
>
> * the first column always displays correctly, with or without an
> expander (and in the latter case, expanded or not).
> * the following columns have the text overlapping their left-side
> resizer by about half a character.
> * subsequent columns display off their vertical boundaries (to the
> right), seemingly depending on the length of the preceeding column.
> Same as if there were no columns but just morphs abutted to one
> another. Manually resizing the previous column to contain the longest
> text gets me back to the previous case (half a char too much to the
> left). In other words, if I'm guessing right, the column clips its
> contents /visually/, but not in relation to their /reported width/.
>
> I'm pretty sure there's something really basic I've missed in the
> layout, but I can't figure it out from the example code nor the
> classes' protocols.
>
> Any hints ?
>
> Thanks.
>
> My code:
>
> * the root list is a collection of associations 'string' -> article instance
> * I'm building a view with the category (expandable) in the first
> column. Once expanded, it shows the article's properties in columns.
>
> CategoriesAndArticlesTree(MorphTreeModel)>>buildTree
>        | treeMorph |
>        treeMorph := (self treeMorphClass on: self)
>                columns: {
>                        MorphTreeColumn new rowMorphGetSelector:
> #categoryOrAuthor.
>                        MorphTreeColumn new
>                                rowMorphGetSelector: #title;
>                                headerButtonLabel: 'Title' font: nil.
>                        MorphTreeColumn new rowMorphGetSelector: #issue.
>                        MorphTreeColumn new rowMorphGetSelector: #foo
>                 }.
>        treeMorph
>                hResizing: #spaceFill; vResizing: #spaceFill;
>                withHLines: true;
>                makeLastColumnUnbounded;
>                resizerWidth: 1.
>        ^ (treeMorph buildContents )
> CategoriesAndArticlesTree>>rootNodeClassFromItem: anItem
>        ^ CategoriesTreeNode
>
> CategoriesTreeNode(MorphTreeNodeModel)>>categoryOrAuthor
>        ^ self theme builder newLabel: item key
> CategoriesTreeNode>>childNodeClassFromItem: anItem
>        ^ ArticlesTreeNode
> CategoriesTreeNode>>childrenItems
>        ^ item value
> the other column-related selectors are implemented and return a nil.
>
> ArticlesTreeNode(MorphTreeNodeModel) implements the column-related
> selectors by returning the appropriate article property wrapped in a
> label.
> ArticlesTreeNode>>categoryOrAuthor
>        ^ self theme builder newLabel: item author
> ArticlesTreeNode>>foo
>        ^ self theme builder newLabel: 'foo'
>
>

Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Stéphane Ducasse
In reply to this post by Alexis Parseghian
Hi alexis

pay attention that (not sure that this is still the case) but alain used subclassing for setting browser while I would have used
composition.
To me the setting browser is not a tree but composed by a tree.

Alain will certainly reply to all your questions.

Stef
Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Alain Plantec-3
In reply to this post by S Krish
Le 06/03/2012 07:49, S Krish a écrit :

> Pay close attention to the example for
> Class  PackageTreeExample
>
>     it uses: method #rootNodeClassFromItem: to display its children
> derived from #rootItems
>
>   It picks up each of the node to display through: thereafter from the
> various node classes it uses: All Nodes class should be a subclass of
> PackageAbstractNodeExample
>
>     #childNodeClassFromItem: and #childrenItems
>
>   It is a beautiful nearly perfect tree morph, I have every used across
> all UI from VC++/ VW/ VA / Java..
>
>
ouah! thanks, cool to read that :)
Alain

Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Alain Plantec-3
In reply to this post by Stéphane Ducasse
Le 06/03/2012 12:35, Stéphane Ducasse a écrit :
> Hi alexis
>
> pay attention that (not sure that this is still the case) but alain used subclassing for setting browser while I would have used
> composition.
it is still the case :(
and it has to be fixed
> To me the setting browser is not a tree but composed by a tree.
yes
Alain
>
> Alain will certainly reply to all your questions.
>
> Stef


Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Alain Plantec-3
In reply to this post by Alexis Parseghian
can I get your code (from an attached change set as an example), it
would be cool to make another example out of this.
btw, I will answer to your questions
Cheers
Alain

Le 06/03/2012 00:13, Alexis Parseghian a écrit :

> I've been playing with MorphTree et al. for the past few days, trying
> to understand how they work. Reading the example code in
> Morphic-MorphTreeWidget-Examples helped. I've also been trying to
> figure out the Settings Browser, but this one I have a hard time following :(
>
> Anyway, I think I've got the basics now : I instantiate a
> MorphTreeMorph when building my window in an subclass of a
> MorphTreeModel. The contents of my model's list get wrapped in the
> appropriate MorphTreeNodeModel subclasses.
>
> I can get the tree to display *what* I want. My problem is with the
> *how* ; more specifically, how to get the columns right.
>
> * the first column always displays correctly, with or without an
> expander (and in the latter case, expanded or not).
> * the following columns have the text overlapping their left-side
> resizer by about half a character.
> * subsequent columns display off their vertical boundaries (to the
> right), seemingly depending on the length of the preceeding column.
> Same as if there were no columns but just morphs abutted to one
> another. Manually resizing the previous column to contain the longest
> text gets me back to the previous case (half a char too much to the
> left). In other words, if I'm guessing right, the column clips its
> contents /visually/, but not in relation to their /reported width/.
>
> I'm pretty sure there's something really basic I've missed in the
> layout, but I can't figure it out from the example code nor the
> classes' protocols.
>
> Any hints ?
>
> Thanks.
>
> My code:
>
> * the root list is a collection of associations 'string' ->  article instance
> * I'm building a view with the category (expandable) in the first
> column. Once expanded, it shows the article's properties in columns.
>
> CategoriesAndArticlesTree(MorphTreeModel)>>buildTree
>         | treeMorph |
>         treeMorph := (self treeMorphClass on: self)
>                 columns: {
>                         MorphTreeColumn new rowMorphGetSelector:
> #categoryOrAuthor.
>                         MorphTreeColumn new
>                                 rowMorphGetSelector: #title;
>                                 headerButtonLabel: 'Title' font: nil.
>                         MorphTreeColumn new rowMorphGetSelector: #issue.
>                         MorphTreeColumn new rowMorphGetSelector: #foo
>                  }.
>         treeMorph
>                 hResizing: #spaceFill; vResizing: #spaceFill;
>                 withHLines: true;
>                 makeLastColumnUnbounded;
>                 resizerWidth: 1.
>         ^ (treeMorph buildContents )
> CategoriesAndArticlesTree>>rootNodeClassFromItem: anItem
>         ^ CategoriesTreeNode
>
> CategoriesTreeNode(MorphTreeNodeModel)>>categoryOrAuthor
>         ^ self theme builder newLabel: item key
> CategoriesTreeNode>>childNodeClassFromItem: anItem
>         ^ ArticlesTreeNode
> CategoriesTreeNode>>childrenItems
>         ^ item value
> the other column-related selectors are implemented and return a nil.
>
> ArticlesTreeNode(MorphTreeNodeModel) implements the column-related
> selectors by returning the appropriate article property wrapped in a
> label.
> ArticlesTreeNode>>categoryOrAuthor
>         ^ self theme builder newLabel: item author
> ArticlesTreeNode>>foo
>         ^ self theme builder newLabel: 'foo'
>


Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Alexis Parseghian
Thanks to all who replied, and sorry about the double post --
something acted up with the send, and the notification came only late
this morning...

I did have a good look at PackageTreeExample : this is the one that
helped me figure out how to use the nodes. It was a bad example to my
problem though, since it's a pure, single-columned  tree.

I finally noticed the difference between my code and the examples, and
the source of the alignment errors I was getting.

All examples return the content of a cell in the form "self theme
someKindOfUIThemeMorph: blah", while I was using "self theme builder
newLabel:".

It turns out that regular label morphs are not properly clipped
(verified by altering SimpleGridExample). All alignment issues were
solved by using "self theme newTextIn: self text: blah" instead of
generating a label morph. The latter, additionally, was ignoring the
TreeMorph's "rowInset:" specification, while the morph generated by
"newTextIn:text:" respects it.

Not exactly a bug, but not something obvious either, since the cell
seems to accept pretty much any kind of morph for its contents.

Alain, I'll take the details and a cleaned-up example off-list with you shortly.

Again, thanks to all for jarring my neurons :)

On Tue, Mar 6, 2012 at 1:40 PM, Alain Plantec <[hidden email]> wrote:
> can I get your code (from an attached change set as an example), it would be
> cool to make another example out of this.
> btw, I will answer to your questions
> Cheers
> Alain
>
> Le 06/03/2012 00:13, Alexis Parseghian a écrit :
>
>> I've been playing with MorphTree et al. for the past few days, trying
[...8<...]

Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Stéphane Ducasse
In reply to this post by Alain Plantec-3

On Mar 6, 2012, at 1:37 PM, Alain Plantec wrote:

> Le 06/03/2012 12:35, Stéphane Ducasse a écrit :
>> Hi alexis
>>
>> pay attention that (not sure that this is still the case) but alain used subclassing for setting browser while I would have used
>> composition.
> it is still the case :(
> and it has to be fixed

you did a good job :)
No worries

>> To me the setting browser is not a tree but composed by a tree.
> yes
> Alain
>>
>> Alain will certainly reply to all your questions.
>>
>> Stef
>
>


Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Stéphane Ducasse
In reply to this post by Alexis Parseghian
Alexis

send it t the list so that we all learn.

Stef

On Mar 6, 2012, at 6:27 PM, Alexis Parseghian wrote:

> Thanks to all who replied, and sorry about the double post --
> something acted up with the send, and the notification came only late
> this morning...
>
> I did have a good look at PackageTreeExample : this is the one that
> helped me figure out how to use the nodes. It was a bad example to my
> problem though, since it's a pure, single-columned  tree.
>
> I finally noticed the difference between my code and the examples, and
> the source of the alignment errors I was getting.
>
> All examples return the content of a cell in the form "self theme
> someKindOfUIThemeMorph: blah", while I was using "self theme builder
> newLabel:".
>
> It turns out that regular label morphs are not properly clipped
> (verified by altering SimpleGridExample). All alignment issues were
> solved by using "self theme newTextIn: self text: blah" instead of
> generating a label morph. The latter, additionally, was ignoring the
> TreeMorph's "rowInset:" specification, while the morph generated by
> "newTextIn:text:" respects it.
>
> Not exactly a bug, but not something obvious either, since the cell
> seems to accept pretty much any kind of morph for its contents.
>
> Alain, I'll take the details and a cleaned-up example off-list with you shortly.
>
> Again, thanks to all for jarring my neurons :)
>
> On Tue, Mar 6, 2012 at 1:40 PM, Alain Plantec <[hidden email]> wrote:
>> can I get your code (from an attached change set as an example), it would be
>> cool to make another example out of this.
>> btw, I will answer to your questions
>> Cheers
>> Alain
>>
>> Le 06/03/2012 00:13, Alexis Parseghian a écrit :
>>
>>> I've been playing with MorphTree et al. for the past few days, trying
> [...8<...]
>


Reply | Threaded
Open this post in threaded view
|

Re: using tree morphs

Alexis Parseghian
On Wed, Mar 7, 2012 at 6:40 PM, Stéphane Ducasse
<[hidden email]> wrote:
> Alexis
>
> send it t the list so that we all learn.
>

sorry, bad reflex on my part I guess. So here they are, as changesets.

SimpleGridExample :

Generates a tabular view on Person instances where cells are editable.
Modified to
a) reduce the number of items to 100 (down from 1000 -- takes several
seconds to build on my machine)
b) set the age of the Person randomly (was just the value of the
sequential counter over Persons)
c) add a read-only text column with a comment about the age, one of
the comments being rather long.
As it stands, it uses "theme newTextIn:text:" in
SimpleGridNodeExample>>ageComment and works OK. Replace it by "theme
builder newLabel:" and see the effect I was describing.

MixedTreeGridExample :

A generalized version of what I was looking into, which is a tabular
view with a hierarchy in the first column. I haven't made it clear in
the example code, but it is possible to display tabular cells at *any*
level of expansion, not only the last one. This now uses theme
newTextIn:text: throughout and works exactly as intended. The code is
commented.

Regards,
A.

SimpleGridExample.1.cs (3K) Download Attachment
MixedTreeGridExample.1.cs (9K) Download Attachment