Hi I want a square morph with a circle or a line at 45 degree inside Now I do not get it. I thought that I needed to specialize drawOnAthensCanvas: so I did BlCell >> drawOnAthensCanvas: aCanvas super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new). Now I do not know how I can specify a shape size So I will use another API than drawShape: Stef
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath. cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50. On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote:
Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas Now I stop but I find bloc too complex. Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now. Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr <mailto:stepharo@free.fr>> wrote:
Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
I don't see any problem here. Rendering in bloc is as complex as athens/cairo, just check what methods AthensCanvas provides and use them. no magic. Cheers, Alex
How to make square element with filled circle inside: 1) Subclass BlElement -> BlCell 2) Override
drawOnSpartaCanvas: aCanvas super drawOnSpartaCanvas: aCanvas. aCanvas setShape: self localBounds; setStrokePaint: Color blue; stroke
3) Override initialize to have circle shape:
initialize super initialize. self shapeDo: [ :aShape | aShape path: BlCirclePath new; fillPaint: Color red ].
4) Open cell in word Easy :)
How to make square element with filled circle inside:
1) Subclass BlElement -> BlCell 2) Override
drawOnSpartaCanvas: aCanvas super drawOnSpartaCanvas: aCanvas. aCanvas setShape: self localBounds; setStrokePaint: Color blue; stroke
3) Override initialize to have circle shape:
initialize super initialize. self shapeDo: [ :aShape | aShape path: BlCirclePath new; fillPaint: Color red ].
4) Open cell in word
Easy :)
Except that I do not understand it. I do not understand why I should do setShape: self localBounds; and why I should do shapeDo: in the initialize This is totally unclear to me. So this means that I cannot program anything I want with it. Imagine I could not find anything simpler than a box with a circle drawn on it and even with the solution I cannot understand it. You see in Morphic this is simple: you have a drawOn: aCanvas method and you know how to draw: aCanvas I do not get the interaction between the draw and the initialize. This is totally unclear. Now I tried and this code did not work in the build 26 so I tried with drawOnAthensCanvas: and it crashed. So I stop. No need to reply to this email and thread. Stef
Hi Stef, I think the example that Alex provided is less advisable and it is misleading :). Itâs indeed interesting that you can do what he shows, but I do not think this is the example that people should see first. I got my hands on an image. Here is an example that is composing two elements: element := BlElement new layoutStrategy: BlBasicLayoutStrategy new; shape: (BlShape new path: BlRectanglePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 4)); extent: 500@500; position: 0@0; addChild: (BlElement new shape: (BlShape new path: BlCirclePath new; fillPaint: Color red); extent: 450@450; position: 25@25). element openInWorld. Is this what you had in mind? Cheers, Doru
On Apr 2, 2016, at 11:38 PM, stepharo <stepharo@free.fr> wrote:
How to make square element with filled circle inside:
1) Subclass BlElement -> BlCell 2) Override drawOnSpartaCanvas: aCanvas super drawOnSpartaCanvas: aCanvas. aCanvas setShape: self localBounds; setStrokePaint: Color blue; stroke
3) Override initialize to have circle shape: initialize super initialize. self shapeDo: [ :aShape | aShape path: BlCirclePath new; fillPaint: Color red ]. 4) Open cell in word
Easy :)
Except that I do not understand it. I do not understand why I should do setShape: self localBounds;
and why I should do shapeDo: in the initialize
This is totally unclear to me. So this means that I cannot program anything I want with it. Imagine I could not find anything simpler than a box with a circle drawn on it and even with the solution I cannot understand it.
You see in Morphic this is simple: you have a drawOn: aCanvas method and you know how to draw: aCanvas I do not get the interaction between the draw and the initialize. This is totally unclear.
Now I tried and this code did not work in the build 26 so I tried with drawOnAthensCanvas: and it crashed. So I stop. No need to reply to this email and thread.
Stef
-- www.tudorgirba.com www.feenk.com "We can create beautiful models in a vacuum. But, to get them effective we have to deal with the inconvenience of reality."
Hi Alex, I think that Stef is looking for a composition example. Could you please provide an example that is more canonical and shows the composition of two elements instead of playing with both drawOnSpartaCanvas and the shape? Cheers, Doru
On Apr 2, 2016, at 8:17 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
How to make square element with filled circle inside:
1) Subclass BlElement -> BlCell 2) Override drawOnSpartaCanvas: aCanvas super drawOnSpartaCanvas: aCanvas. aCanvas setShape: self localBounds; setStrokePaint: Color blue; stroke
3) Override initialize to have circle shape: initialize super initialize. self shapeDo: [ :aShape | aShape path: BlCirclePath new; fillPaint: Color red ]. 4) Open cell in word
Easy :)
-- www.tudorgirba.com www.feenk.com "We can create beautiful models in a vacuum. But, to get them effective we have to deal with the inconvenience of reality."
I'm pretty sure we don't understand a meaning of composition identically. This is how I understand it: https://en.m.wikipedia.org/wiki/Composition_(visual_arts) "In graphic design for press and desktop publishing composition is commonly referred to as page layout." Design for press is inspiration of modern ui design techniques, for example material design. Concentrate on "page layout". Then comes the following question: if composition is archived through layout of elements why Stef tries to manually draw shapes instead of composing two elements? Howto: 1) Create an element with rectangle shape. 2) Create an element with circle shape. 3) Add circle element to rectangle element. 4) Change layout params of the circle element to match parent both vertically and horizontally 5) if needed set padding/margin. There is even no need to care about drawing if it's complicated. On Apr 3, 2016 12:26 AM, "Tudor Girba" <tudor@tudorgirba.com> wrote:
Hi Alex,
I think that Stef is looking for a composition example. Could you please provide an example that is more canonical and shows the composition of two elements instead of playing with both drawOnSpartaCanvas and the shape?
Cheers, Doru
On Apr 2, 2016, at 8:17 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
How to make square element with filled circle inside:
1) Subclass BlElement -> BlCell 2) Override drawOnSpartaCanvas: aCanvas super drawOnSpartaCanvas: aCanvas. aCanvas setShape: self localBounds; setStrokePaint: Color blue; stroke
3) Override initialize to have circle shape: initialize super initialize. self shapeDo: [ :aShape | aShape path: BlCirclePath new; fillPaint: Color red ]. 4) Open cell in word
Easy :)
-- www.tudorgirba.com www.feenk.com
"We can create beautiful models in a vacuum. But, to get them effective we have to deal with the inconvenience of reality."
Hi,
On Apr 3, 2016, at 12:46 AM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
I'm pretty sure we don't understand a meaning of composition identically. This is how I understand it:
https://en.m.wikipedia.org/wiki/Composition_(visual_arts)
"In graphic design for press and desktop publishing composition is commonly referred to as page layout."
Design for press is inspiration of modern ui design techniques, for example material design.
Concentrate on "page layout". Then comes the following question: if composition is archived through layout of elements why Stef tries to manually draw shapes instead of composing two elements? Howto: 1) Create an element with rectangle shape. 2) Create an element with circle shape. 3) Add circle element to rectangle element. 4) Change layout params of the circle element to match parent both vertically and horizontally 5) if needed set padding/margin.
There is even no need to care about drawing if it's complicated.
That is exactly the point :). I think for such scenarios we should encourage people to use composition of elements. I think that Stef has a use case of the way the element should look like in the end, and he wants to get it done, and I think we should provide examples that guide him to what the best route should be. Anyway, this probably reveals the miscommunication. @Stef: did you want to necessarily play with the low level drawing, or do you just want to get to an element with a rectangle that has a circle inside? Cheers, Doru
On Apr 3, 2016 12:26 AM, "Tudor Girba" <tudor@tudorgirba.com> wrote: Hi Alex,
I think that Stef is looking for a composition example. Could you please provide an example that is more canonical and shows the composition of two elements instead of playing with both drawOnSpartaCanvas and the shape?
Cheers, Doru
On Apr 2, 2016, at 8:17 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
How to make square element with filled circle inside:
1) Subclass BlElement -> BlCell 2) Override drawOnSpartaCanvas: aCanvas super drawOnSpartaCanvas: aCanvas. aCanvas setShape: self localBounds; setStrokePaint: Color blue; stroke
3) Override initialize to have circle shape: initialize super initialize. self shapeDo: [ :aShape | aShape path: BlCirclePath new; fillPaint: Color red ]. 4) Open cell in word
Easy :)
-- www.tudorgirba.com www.feenk.com
"We can create beautiful models in a vacuum. But, to get them effective we have to deal with the inconvenience of reality."
-- www.tudorgirba.com www.feenk.com "Innovation comes in the least expected form. That is, if it is expected, it already happened."
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation.
From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one. Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen. A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s).
From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle. What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s). Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction And that could be completely different from shape(s) you may need to draw it on the screen. Stef
On Apr 2, 2016 4:57 PM, "stepharo" < <stepharo@free.fr>stepharo@free.fr> wrote:
Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape. For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly. So, overall when we talking about shapes, we need to talk about three different kinds of them: - UI interaction shape - clipping shape - shape(s) used to draw those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want. Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI. On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" < <stepharo@free.fr>stepharo@free.fr> wrote:
Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Hi Igor, Thanks for this nice description :). Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction. When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition. The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power. Does this make sense for you? Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com "Reasonable is what we are accustomed with."
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other. For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot. As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles. You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves. To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black. Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
If you want to change clicking behaviour you need to override one single method. Everything you wrote with unreadable amount of characters is for nothing. All mentioned stuff is possible. On Apr 3, 2016 10:30 AM, "Igor Stasenko" <siguctua@gmail.com> wrote:
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other.
For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot.
As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent
or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling
You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles.
You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves.
To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black.
Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
On 3 April 2016 at 12:08, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
If you want to change clicking behaviour you need to override one single method.
it is not about just clicking behavior. Sure i can override every single method to get behavior i want, at any point in system i need. Then what is purpose of making any design, if it all goes down to 'oh.. if you don't like something , just go and do it youself'? Seriously?
Everything you wrote with unreadable amount of characters is for nothing.
Haha.. If you can't read something, it does not means, that there's nothing. It just you cannot read.
All mentioned stuff is possible.
Details, that statement requires. You seem don't want to demonstrate that your concept is sound. Because i wanna see how it goes.. So far i have doubts about it, which i tried to formulate in previous posts.. i may not understand in it something, something you understand.. and i wanna see where i wrong. And in response i got nothing, no arguments, zero. This is exactly, what called 'nothing'.
On Apr 3, 2016 10:30 AM, "Igor Stasenko" <siguctua@gmail.com> wrote:
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other.
For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot.
As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent
or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling
You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles.
You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves.
To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black.
Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Hello Igor I would like to apologize for my bad tone in previous email. I misunderstood your good will to help and improve design by finding special cases that we didn't manage to cover. I indeed would like to show you that design sounds. Let's play with more concrete examples. To start let's take one mentioned by you, about rectangle morph that answers to events only inside a circle. I will create a repo for PUBLIC bloc experiments so that all of us could try it in practice. Your help is highly appreciated and we are happy to see you :) Cheers On 3 April 2016 at 12:08, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
If you want to change clicking behaviour you need to override one single method.
it is not about just clicking behavior. Sure i can override every single method to get behavior i want, at any point in system i need. Then what is purpose of making any design, if it all goes down to 'oh.. if you don't like something , just go and do it youself'? Seriously?
Everything you wrote with unreadable amount of characters is for nothing.
Haha.. If you can't read something, it does not means, that there's nothing. It just you cannot read.
All mentioned stuff is possible.
Details, that statement requires. You seem don't want to demonstrate that your concept is sound. Because i wanna see how it goes.. So far i have doubts about it, which i tried to formulate in previous posts.. i may not understand in it something, something you understand.. and i wanna see where i wrong. And in response i got nothing, no arguments, zero. This is exactly, what called 'nothing'.
On Apr 3, 2016 10:30 AM, "Igor Stasenko" <siguctua@gmail.com> wrote:
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other.
For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot.
As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent
or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling
You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles.
You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves.
To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black.
Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Hi Alex, Thanks for this :) Cheers, Doru
On Apr 3, 2016, at 12:14 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
Hello Igor
I would like to apologize for my bad tone in previous email. I misunderstood your good will to help and improve design by finding special cases that we didn't manage to cover. I indeed would like to show you that design sounds.
Let's play with more concrete examples. To start let's take one mentioned by you, about rectangle morph that answers to events only inside a circle.
I will create a repo for PUBLIC bloc experiments so that all of us could try it in practice.
Your help is highly appreciated and we are happy to see you :)
Cheers
On 3 April 2016 at 12:08, Aliaksei Syrel <alex.syrel@gmail.com> wrote: If you want to change clicking behaviour you need to override one single method.
it is not about just clicking behavior. Sure i can override every single method to get behavior i want, at any point in system i need. Then what is purpose of making any design, if it all goes down to 'oh.. if you don't like something , just go and do it youself'? Seriously? Everything you wrote with unreadable amount of characters is for nothing.
Haha.. If you can't read something, it does not means, that there's nothing. It just you cannot read.
All mentioned stuff is possible.
Details, that statement requires. You seem don't want to demonstrate that your concept is sound. Because i wanna see how it goes.. So far i have doubts about it, which i tried to formulate in previous posts.. i may not understand in it something, something you understand.. and i wanna see where i wrong. And in response i got nothing, no arguments, zero. This is exactly, what called 'nothing'.
On Apr 3, 2016 10:30 AM, "Igor Stasenko" <siguctua@gmail.com> wrote:
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com> wrote: Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other.
For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot.
As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent
or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling
You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles.
You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves.
To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black.
Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com "Next time you see your life passing by, say 'hi' and get to know her."
On 3 April 2016 at 13:14, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
Hello Igor
I would like to apologize for my bad tone in previous email. I misunderstood your good will to help and improve design by finding special cases that we didn't manage to cover. I indeed would like to show you that design sounds.
Let's play with more concrete examples. To start let's take one mentioned by you, about rectangle morph that answers to events only inside a circle.
I will create a repo for PUBLIC bloc experiments so that all of us could try it in practice.
Your help is highly appreciated and we are happy to see you :)
Thank you, Aliaksei. If you have an impression that i came here to troll you or to argue just for the sake of arguing and wasting your time, please trust me, i am not. I spent a lot of time thinking about this stuff and making it and discussing it over and over again with many people, including Alain, Stef and others.. and so, i am not a stranger that passing by, i honestly want to see it fly, be smooth and elegant , close to perfect, but not crawl on a set of kludges.
Cheers
On 3 April 2016 at 12:08, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
If you want to change clicking behaviour you need to override one single method.
it is not about just clicking behavior. Sure i can override every single method to get behavior i want, at any point in system i need. Then what is purpose of making any design, if it all goes down to 'oh.. if you don't like something , just go and do it youself'? Seriously?
Everything you wrote with unreadable amount of characters is for nothing.
Haha.. If you can't read something, it does not means, that there's nothing. It just you cannot read.
All mentioned stuff is possible.
Details, that statement requires. You seem don't want to demonstrate that your concept is sound. Because i wanna see how it goes.. So far i have doubts about it, which i tried to formulate in previous posts.. i may not understand in it something, something you understand.. and i wanna see where i wrong. And in response i got nothing, no arguments, zero. This is exactly, what called 'nothing'.
On Apr 3, 2016 10:30 AM, "Igor Stasenko" <siguctua@gmail.com> wrote:
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other.
For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot.
As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent
or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling
You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles.
You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves.
To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black.
Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com> wrote:
Oh, yeah.. i missed one more kind of shape, you may want to introduce: - clipping shape.
For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly.
So, overall when we talking about shapes, we need to talk about three different kinds of them:
- UI interaction shape - clipping shape - shape(s) used to draw
those three may or may not coincide into single one, depending on complexity and what you wanna do.. But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want.
Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI.
On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com> wrote:
On 2 April 2016 at 20:59, stepharo <stepharo@free.fr> wrote:
Le 2/4/16 17:31, Aliaksei Syrel a écrit :
You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath.
cell shape: (BlShape new path: BlCirclePath new; strokePaint: (BlStrokePaint new paint: Color blue; width: 1)). cell extent: 50@50.
But this is not what I want! As I mentioned in a mail that was sent but never arrived. I want a square and this is why I did
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas
Now I stop but I find bloc too complex.
Sorry but I cannot lose time like that and just get frustrated at the end. I will use the athens canvas directly and stay in morph for now.
I think there's a bit of misconception. In Athens, shape representing any area you wanna fill with paint. Period. It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen.
So, the first point in misconception comes from 'self shape:'.. It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one.
Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen.
A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). From that perspective, this is nice, resource saving, approach. But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). You should still be able to define shape(s) on the fly or change it on the fly, dynamically.
Another problematic is that you may want to use different shapes for a) painting morph on screen b) defining geometry of the morph for UI interactions. As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle.
What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s).
Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: - intersection of - union - subtraction
And that could be completely different from shape(s) you may need to draw it on the screen.
Stef
On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr> wrote: Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Now I do not know how I can specify a shape size
So I will use another API than drawShape:
Stef
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com www.feenk.com
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Hi 2016-04-03 11:08 GMT+02:00 Aliaksei Syrel <alex.syrel@gmail.com>:
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
It is indeed logical :) However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end). Do you agree with that and also that in most cases we want to change them all together just sending one message? :) Cheers Alex On Apr 3, 2016 12:20 PM, "Denis Kudriashov" <dionisiydk@gmail.com> wrote:
Hi
2016-04-03 11:08 GMT+02:00 Aliaksei Syrel <alex.syrel@gmail.com>:
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
On 3 April 2016 at 13:27, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
It is indeed logical :)
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
But wait, what i saw in this thread: Stef presented a simple use case - he wants to draw a rectangle plus circle or a line.. and got lost.. confused and frustrated. And i am far to see how such use case can be called something exceptionally rare. Do you? The goal of good design is to make common cases extremely simple, non-common cases - harder. But not impossible. And by impossible i mean not that you cannot do anything by yourself, but what you can do using existing framework. The fact that i can override and rewrite anything and make it my way - is not a valid argument. Yes, i made a slight detour in discussion, to demonstrate that actually single shape per morph is no go.. And there's multiple shapes can be involved and each for own role. And allowing only a single one feels a bit limiting, as to me. But of course i understand, that it is not so common, except when i wanna draw a label on top of background, which requires at least two shapes. :) As for clipping/ui shapes, i don't understand, it is really not that hard to do, i.e.: clippingShape ^ clippingShape ifNil: [ self shape ] .. which means you can still have a single shape by default, but in case you need - here you go, you free to define own. But anyways.. All i want is to be convinced that my fears are not that bad. Btw, i have a question about your statement, quote: You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath. Hmm. At least in Athens, by design AthensPath is a shape. It is a shape, that is drawn by Athens. Path is just a single concrete case how you could define a shape. Rectangle is another one.. And there's no limitation in Athens, what may represent a shape, as long as it conforms to AthensShape protocol, which also means, if you look at it, it has #paintFillsUsing:on: , which implies, that it actually should know how to draw itself. And of course, since it knows what areas it covers it has insights about own geometry.. but such details are not exposed to outside, since it would be very hard to encode all possible ways to represent shape(s) by some kind of common data, like paths. Are you talking about Bloc shapes? Then it is indeed a pity, if such statement are correct in terms of Bloc. Because then it introducing another kind of shapes in addition to existing kind of shapes introduced by Athens.. something different and not really compatible. Which serves as a source of confusion. I am not arguing, maybe such thing was necessary, but i would, at least then call it different to avoid potential confusion. Do you agree with that and also that in most cases we want to change them
all together just sending one message? :)
Cheers Alex On Apr 3, 2016 12:20 PM, "Denis Kudriashov" <dionisiydk@gmail.com> wrote:
Hi
2016-04-03 11:08 GMT+02:00 Aliaksei Syrel <alex.syrel@gmail.com>:
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
-- Best regards, Igor Stasenko.
I completely agree with you now, Igor :) The idea that I *proposed* during Pharo days is to make BlShape polymorphic with what athens have. I did not implement it yet I work on it just right now. I suppose that I explained me wrong to Stef and he started thinking that it is *already* implemented. On my road back from Pharo days I started working on what Stef wanted to do yesterday. I my example I just wanted to show Stef how he can solve his problem just right now, without saying "Oh, Stef, you know, please wait one more week". Also that was the idea why I started implementing own implementation of Athens Api and named it Sparta. Specifically to remove amount of shapes/pathes/paints used in Bloc. I was planning to finish it before I send an announcement email to pharo mailing list saying officially that bloc is released to alpha. I discussed it on Pharo days and we agreed to wait until announcement. And now I'm frustrated that people don't listen to me and try to use product before official release just in the middle of refactoring. What you are stating in this discussion will be implemented early or later.
On 3 April 2016 at 14:37, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
I completely agree with you now, Igor :)
The idea that I *proposed* during Pharo days is to make BlShape polymorphic with what athens have. I did not implement it yet I work on it just right now.
I suppose that I explained me wrong to Stef and he started thinking that it is *already* implemented. On my road back from Pharo days I started working on what Stef wanted to do yesterday.
I my example I just wanted to show Stef how he can solve his problem just right now, without saying "Oh, Stef, you know, please wait one more week".
Also that was the idea why I started implementing own implementation of Athens Api and named it Sparta. Specifically to remove amount of shapes/pathes/paints used in Bloc. I was planning to finish it before I send an announcement email to pharo mailing list saying officially that bloc is released to alpha.
Can you shed more light on this? I need your motivation/reasoning behind it. I tried in Athens to keep a minimal set of protocol(s), so that there's no need to learn numerous methods to start using it. The shapes/paints thing is central in Athens.. so, if you see how it can be made even simpler, i am all ears to hear details. In any case, what i can tell from your statement above is to remove unnecessary bloat.. which is always welcome. But why that requires changes in Athens API, instead of changes in Bloc?
I discussed it on Pharo days and we agreed to wait until announcement. And now I'm frustrated that people don't listen to me and try to use product before official release just in the middle of refactoring.
No, i am not using it, yet.. The only 'people' was Stef himself :)
What you are stating in this discussion will be implemented early or later.
-- Best regards, Igor Stasenko.
2016-04-03 12:27 GMT+02:00 Aliaksei Syrel <alex.syrel@gmail.com>:
It is indeed logical :)
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
Do you agree with that and also that in most cases we want to change them all together just sending one message? :)
I agree. But Igor shows trivial example: label with rectangle background.
Hi, Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...). I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement. In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle. For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me. Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc. It seems to me that Bloc is not made to be used direclty as a graphical framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework". PS: @Alex, what are the planned refactoring? I'm lost in the new intentions and in the roadmap of Bloc... Regards, Glenn. ----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr> wrote:
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical
framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form? And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
PS: @Alex, what are the planned refactoring? I'm lost in the new intentions
and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
On 3 April 2016 at 16:20, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr> wrote:
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical
framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form?
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
<acid mode on> .. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method. And you talking about 'sophistication' after that? </acid mode off>
PS: @Alex, what are the planned refactoring? I'm lost in the new intentions
and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as: defaultShape
^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy? .. to me it feels like: okay, what we need to do, to prevent overrides of
our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :) Don't forget that there was a customer *requirement* concerning bloc: Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago. Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :) Cheers, Alex On Sun, Apr 3, 2016 at 3:37 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 16:20, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr> wrote:
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical
framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form?
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
<acid mode on> .. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
And you talking about 'sophistication' after that?
</acid mode off>
PS: @Alex, what are the planned refactoring? I'm lost in the new
intentions and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
On 3 April 2016 at 17:58, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
And you lost me here.. That is complete nonsense.. from any perspective.
Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as:
defaultShape
^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy?
Nope. (see bottom of reply why)
.. to me it feels like: okay, what we need to do, to prevent overrides
of our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :) Don't forget that there was a customer *requirement* concerning bloc:
Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago.
Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :)
Nope. Because it would be beautiful, if your statements would be reflected in reality and by reality. In your example #defaultShape method, you simply isolating some behavior into a separate method. It does not changes anything. You want to achieve to be able to change shapes on the fly. Good. A honourable goal. And welcoming. No objections here. But can we achieve it without losing being able to change the color of shape on the fly. Please? :) The way you introducing it goes straightly into conflict with: i want to be able to draw anything, the way i feel and like. You proposing a bad trade: oh yeah, you wanted to change shapes on the fly.. good.. but at cost of unable to draw anything else than simple rectangles in simple order.. Well.. i am not buying such trade. Can you sweeten a deal? The point is, that shape is not the only thing you need to put into equation in order to get thing on the screen.. You also need paint. And that's the reason why you have fillPaint: (BlColorPaint new color: (Color yellow)); (lets put aside the hardcoding of color in unrelated place (defaultShape).. for the sake of example) but does that fully covers all and any possible ways and needs of drawing? Nope! Again not.. And voila, say welcome to composite "shapes" or "elements" or call it as you like it. But does that fully covers all and any possible ways you can draw something with Athens? Nope, it is not. Again. Sorry. You can achieve that only if you completely encode all possible operations and features provided by Athens using some kind of command pattern and put them in 'element' or 'compositeElement' or 'compositeOfCompositeElementsComposition' whatever. For instance, how you going to encode AthensPaintMode into your elements? I guess you will offer to kill it with your 'it is not used so often' knife. Can't you see that you basically creating a wrapper for all Athens feature set. I can tell you that you wasting effort: you cannot get anything extra by doing it. Except from extra complexity. And for what? Something that already there and can be used out of the box. If you don't like Athens API - go on, and change it. Make it better and more convenient to use. But encapsulating all possible combinations of all possible drawing operations? Good luck with that.
Cheers, Alex
On Sun, Apr 3, 2016 at 3:37 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 16:20, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr> wrote:
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical
framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form?
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
<acid mode on> .. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
And you talking about 'sophistication' after that?
</acid mode off>
PS: @Alex, what are the planned refactoring? I'm lost in the new
intentions and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
This means that any abstraction/wrapper around athens will fail. What if we would remove drawingShape and by default leave drawOn: method to be empty. That way we would not put any constraints on rendering part. user just gets athens canvas and can do whatever she wants. Instead we would have only clipping shape and event area shape. What do you think? :) Cheers, Alex On Sun, Apr 3, 2016 at 6:04 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 17:58, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
And you lost me here.. That is complete nonsense.. from any perspective.
Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as:
defaultShape
^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy?
Nope. (see bottom of reply why)
.. to me it feels like: okay, what we need to do, to prevent overrides
of our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :) Don't forget that there was a customer *requirement* concerning bloc:
Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago.
Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :)
Nope. Because it would be beautiful, if your statements would be reflected in reality and by reality. In your example #defaultShape method, you simply isolating some behavior into a separate method. It does not changes anything.
You want to achieve to be able to change shapes on the fly. Good. A honourable goal. And welcoming. No objections here.
But can we achieve it without losing being able to change the color of shape on the fly. Please? :) The way you introducing it goes straightly into conflict with: i want to be able to draw anything, the way i feel and like. You proposing a bad trade: oh yeah, you wanted to change shapes on the fly.. good.. but at cost of unable to draw anything else than simple rectangles in simple order.. Well.. i am not buying such trade. Can you sweeten a deal?
The point is, that shape is not the only thing you need to put into equation in order to get thing on the screen.. You also need paint. And that's the reason why you have fillPaint: (BlColorPaint new color: (Color yellow));
(lets put aside the hardcoding of color in unrelated place (defaultShape).. for the sake of example) but does that fully covers all and any possible ways and needs of drawing? Nope! Again not.. And voila, say welcome to composite "shapes" or "elements" or call it as you like it. But does that fully covers all and any possible ways you can draw something with Athens? Nope, it is not. Again. Sorry. You can achieve that only if you completely encode all possible operations and features provided by Athens using some kind of command pattern and put them in 'element' or 'compositeElement' or 'compositeOfCompositeElementsComposition' whatever.
For instance, how you going to encode AthensPaintMode into your elements? I guess you will offer to kill it with your 'it is not used so often' knife.
Can't you see that you basically creating a wrapper for all Athens feature set. I can tell you that you wasting effort: you cannot get anything extra by doing it. Except from extra complexity. And for what? Something that already there and can be used out of the box.
If you don't like Athens API - go on, and change it. Make it better and more convenient to use. But encapsulating all possible combinations of all possible drawing operations? Good luck with that.
Cheers, Alex
On Sun, Apr 3, 2016 at 3:37 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 16:20, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr> wrote:
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical
framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form?
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
<acid mode on> .. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
And you talking about 'sophistication' after that?
</acid mode off>
PS: @Alex, what are the planned refactoring? I'm lost in the new
intentions and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
On 3 April 2016 at 19:23, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
This means that any abstraction/wrapper around athens will fail.
I would not say it like that. WIth decent effort you can do it. But the right question here: do you really need it? You missing some features for shapes? Good.. make new one(s) , just teach them how to draw themselves on Athens canvas and you done.
For instance, for using shape in UI test it missing, #containsPoint: behavior. And for clipping, it missing clipOn: aCanvas during: aBlock behavior. So, you can choose to either extend basic protocol in Athens by implementing this feature(s) for all existing shapes, or introduce own shapes, polymorphic with AthensShape(s) but in addition implementing these protocols. Then you can use same shape for drawing, clipping and UI testing. Job done. You basically missing those two methods and you are done. And instead you inventing something that not only solves the problem, but puts a lot of restrictions on what you can draw using Block and how.
What if we would remove drawingShape and by default leave drawOn: method to be empty. That way we would not put any constraints on rendering part. user just gets athens canvas and can do whatever she wants.
Well, a root morph cannot put any assumptions how his subclasses would want to draw themselves.. So, really, no assumptions means empty method. Sounds good to me. Well, it is empty, and just server as a placeholder indicating a protocol and a point of customization, nothing else. (Stef will most probably force you to put a nice comment there ;)
Instead we would have only clipping shape and event area shape. What do you think? :)
That's what i proposing. What i think i already wrote in this thread :) It is up to you to accept or reject the idea. Or propose something even better and simpler. Or by any other participants of discussion. And why you surrender so fast? What if i am wrong? What is going on? Lets make it as best as we can, not 'as Igor says'. :)
Cheers, Alex
On Sun, Apr 3, 2016 at 6:04 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 17:58, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
And you lost me here.. That is complete nonsense.. from any perspective.
Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as:
defaultShape
^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy?
Nope. (see bottom of reply why)
.. to me it feels like: okay, what we need to do, to prevent overrides
of our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :) Don't forget that there was a customer *requirement* concerning bloc:
Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago.
Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :)
Nope. Because it would be beautiful, if your statements would be reflected in reality and by reality. In your example #defaultShape method, you simply isolating some behavior into a separate method. It does not changes anything.
You want to achieve to be able to change shapes on the fly. Good. A honourable goal. And welcoming. No objections here.
But can we achieve it without losing being able to change the color of shape on the fly. Please? :) The way you introducing it goes straightly into conflict with: i want to be able to draw anything, the way i feel and like. You proposing a bad trade: oh yeah, you wanted to change shapes on the fly.. good.. but at cost of unable to draw anything else than simple rectangles in simple order.. Well.. i am not buying such trade. Can you sweeten a deal?
The point is, that shape is not the only thing you need to put into equation in order to get thing on the screen.. You also need paint. And that's the reason why you have fillPaint: (BlColorPaint new color: (Color yellow));
(lets put aside the hardcoding of color in unrelated place (defaultShape).. for the sake of example) but does that fully covers all and any possible ways and needs of drawing? Nope! Again not.. And voila, say welcome to composite "shapes" or "elements" or call it as you like it. But does that fully covers all and any possible ways you can draw something with Athens? Nope, it is not. Again. Sorry. You can achieve that only if you completely encode all possible operations and features provided by Athens using some kind of command pattern and put them in 'element' or 'compositeElement' or 'compositeOfCompositeElementsComposition' whatever.
For instance, how you going to encode AthensPaintMode into your elements? I guess you will offer to kill it with your 'it is not used so often' knife.
Can't you see that you basically creating a wrapper for all Athens feature set. I can tell you that you wasting effort: you cannot get anything extra by doing it. Except from extra complexity. And for what? Something that already there and can be used out of the box.
If you don't like Athens API - go on, and change it. Make it better and more convenient to use. But encapsulating all possible combinations of all possible drawing operations? Good luck with that.
Cheers, Alex
On Sun, Apr 3, 2016 at 3:37 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 16:20, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr> wrote:
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical
framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form?
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
<acid mode on> .. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
And you talking about 'sophistication' after that?
</acid mode off>
PS: @Alex, what are the planned refactoring? I'm lost in the new
intentions and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Le 3/4/16 18:23, Aliaksei Syrel a écrit :
This means that any abstraction/wrapper around athens will fail.
What if we would remove drawingShape and by default leave drawOn: method to be empty. That way we would not put any constraints on rendering part. user just gets athens canvas and can do whatever she wants.
Instead we would have only clipping shape and event area shape. What do you think? :)
I have the impression that this is a good solution.
Cheers, Alex
On Sun, Apr 3, 2016 at 6:04 PM, Igor Stasenko <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote:
On 3 April 2016 at 17:58, Aliaksei Syrel <alex.syrel@gmail.com <mailto:alex.syrel@gmail.com>> wrote:
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as:
defaultShape ^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy?
Nope. (see bottom of reply why)
.. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :) Don't forget that there was a customer *requirement* concerning bloc:
Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago.
Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :)
Nope. Because it would be beautiful, if your statements would be reflected in reality and by reality. In your example #defaultShape method, you simply isolating some behavior into a separate method. It does not changes anything.
You want to achieve to be able to change shapes on the fly. Good. A honourable goal. And welcoming. No objections here.
But can we achieve it without losing being able to change the color of shape on the fly. Please? :) The way you introducing it goes straightly into conflict with: i want to be able to draw anything, the way i feel and like. You proposing a bad trade: oh yeah, you wanted to change shapes on the fly.. good.. but at cost of unable to draw anything else than simple rectangles in simple order.. Well.. i am not buying such trade. Can you sweeten a deal?
The point is, that shape is not the only thing you need to put into equation in order to get thing on the screen.. You also need paint. And that's the reason why you have fillPaint: (BlColorPaint new color: (Color yellow));
(lets put aside the hardcoding of color in unrelated place (defaultShape).. for the sake of example) but does that fully covers all and any possible ways and needs of drawing? Nope! Again not.. And voila, say welcome to composite "shapes" or "elements" or call it as you like it. But does that fully covers all and any possible ways you can draw something with Athens? Nope, it is not. Again. Sorry. You can achieve that only if you completely encode all possible operations and features provided by Athens using some kind of command pattern and put them in 'element' or 'compositeElement' or 'compositeOfCompositeElementsComposition' whatever.
For instance, how you going to encode AthensPaintMode into your elements? I guess you will offer to kill it with your 'it is not used so often' knife.
Can't you see that you basically creating a wrapper for all Athens feature set. I can tell you that you wasting effort: you cannot get anything extra by doing it. Except from extra complexity. And for what? Something that already there and can be used out of the box.
If you don't like Athens API - go on, and change it. Make it better and more convenient to use. But encapsulating all possible combinations of all possible drawing operations? Good luck with that.
Cheers, Alex
On Sun, Apr 3, 2016 at 3:37 PM, Igor Stasenko <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote:
On 3 April 2016 at 16:20, Igor Stasenko <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote:
On 3 April 2016 at 15:28, Glenn Cavarlé <glenn@cavarle.fr <mailto:glenn@cavarle.fr>> wrote:
Hi,
Aliaksei Syrel wrote > However, in most UI of applications (in web, mobile) it is extremely rare > that clipping or event handling areas differ from drawing one (visual one > - > one that user sees in the end).
It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
Thanks for explanation.. Now i have a hard time understanding, what is the purpose of so-called 'element'. Element of what? What its role? What its interaction between morphs and shapes, and what you see & feel on the screen?
>From your description, what i can tell is that it is completely unnecessary. You have morphs to define hierarchy/composition. And you can use shapes to define geometry for UI/clipping. As for drawing - there's no need to put any constraints, you don't have to even mention that there are shapes involved. It is indeed, an implementation detail from that perspective, since you drawing things using Athens, and it uses shapes to define affected regions. But that completely orthogonal to what happens at UI level. Thus, it is very surprising to me see following code snippet:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
because it is really seems like encapsulation of what you gonna draw.. and putting it into #initialize method in some form?
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
<acid mode on> .. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
And you talking about 'sophistication' after that? </acid mode off>
PS: @Alex, what are the planned refactoring? I'm lost in the new intentions and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Hi Alex, Igor and others, this discussion is interesting to follow. GUI frameworks are hard... Le 03/04/2016 16:58, Aliaksei Syrel a écrit :
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as:
defaultShape ^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy?
If you don't tell me there is a cost for creating a shape in athens, I'll wonder if you're not asking me to optimise by caching a shape; and that is over-engineering.
.. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :)
I wonder if that "shape" thing is not something like the difference between Roassal and Trachel: RT vs TR objects. And, yes, for me, the RT/TR hierarchy is a reimplementation of objects over Athens, and the end result is that it is easy to compose existing objects in Roassal and hard to extend it.
Don't forget that there was a customer *requirement* concerning bloc:
Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago.
If that is your requirement, then this is bad. It's a demo requirement with costly consequences. Does it apply in real life in a system where recreating a complete Morph is so cheap (witness FastTable!)? I'd say no.
Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :)
It is, but it tells of complexity: UI behavior composition (not only graphics). Extending elements may also require extending shapes and understanding how they interact and compose. Regards, Thierry
On 3 April 2016 at 19:43, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Hi Alex, Igor and others,
this discussion is interesting to follow. GUI frameworks are hard...
Le 03/04/2016 16:58, Aliaksei Syrel a écrit :
And you lost me here.. That is complete nonsense.. from any perspective. Can i unsee this code, please? :)
If I would say that we have defaultShape method and it can be overridden as:
defaultShape ^ BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new
would it make you happy?
If you don't tell me there is a cost for creating a shape in athens, I'll wonder if you're not asking me to optimise by caching a shape; and that is over-engineering.
Of course, creating shapes has own cost, as anything else. But, guess what, you having caching mechanism in Athens out of the box, if you don't happy with performance.
.. to me it feels like: okay, what we need to do, to prevent overrides of our beloved default #drawOn: method.
You are wrong concerning preventing to override drawOn :)
I wonder if that "shape" thing is not something like the difference between Roassal and Trachel: RT vs TR objects. And, yes, for me, the RT/TR hierarchy is a reimplementation of objects over Athens, and the end result is that it is easy to compose existing objects in Roassal and hard to extend it.
Sad. Sarcasm tries to flow from my tongue. But i will keep my mouth shut. No comments :)
Don't forget that there was a customer *requirement* concerning bloc:
Can we change how morph looks on fly? Can we create a rectangle morph and change it's shape from rectangle to circle? Because it can nicely show while presenting that *Pharo is live system*. I'm pretty sure Stef said it once ago.
If that is your requirement, then this is bad.
It's a demo requirement with costly consequences. Does it apply in real life in a system where recreating a complete Morph is so cheap (witness FastTable!)? I'd say no.
Do you see how bloc story can nicely be told:
We have basic UI elements and each element has shape that can be easily changed live. Shape is defined by a path which can be filled or stroked using a paint. Complex elements can be created as composition of elements with basic shapes (rectangle, circle).
Isn't it beautiful? :)
It is, but it tells of complexity: UI behavior composition (not only graphics). Extending elements may also require extending shapes and understanding how they interact and compose.
That is road to nowhere. You already having morphs for composition. No need to introduce 'elements' to compose something inside composition of morphs.. If you cannot do something out of composition of morphs, what makes you think that you can do it introducing another layer of composition? Maybe you shall think that composition is a wrong tool in that case?
Regards,
Thierry
-- Best regards, Igor Stasenko.
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
Igor I could understand that if I want a clickable rectangle I have to initialise it with such shape. Now what I could not achieve was to get a circle drawn on it. Sadly :) Stef
On 3 April 2016 at 18:30, stepharo <stepharo@free.fr> wrote:
BlCell>>initialize super initialize. self shape: (BlShape new fillPaint: (BlColorPaint new color: (Color yellow)); path: BlRectanglePath new); extent: self extent
Igor I could understand that if I want a clickable rectangle I have to initialise it with such shape. Now what I could not achieve was to get a circle drawn on it.
Sadly :)
No, it doesn't sounds like that to me. It sounds like:
- you can have your clickable rectangle, but only if you define a color of clickable region - "Color yellow". If you don't define color of clickable region - then system cannot derive from such incomplete data, what region is clickable and what not :)
Stef
-- Best regards, Igor Stasenko.
I did not want a square with a clickable circle. I just wanted a square with a drawn circle on it and I do not understand why I should compose a new morph just for that. I did not get how draw and morph composition are working. I tried to draw the circle myself and I fall into a wrong version that I should be use story. Stef Le 3/4/16 14:28, Glenn Cavarlé a écrit :
Hi,
Aliaksei Syrel wrote
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end). It is the same for desktop UI (Qt, JavaFx,...).
I think the misunderstanding come from "shape", so let us forget BlShape and concentrate on BlElement.
In fact, using Bloc now, If we want a Rectangle with an clickable inner Circle, we have to defined 2 elements, the Rectangle one and the Circle one (subclass of BlElement or using script style). The CircleElement must be the child of the RectangleElement but we don't have to override any method or to rewire CircleElement events back to its parent, we just need to add an event listener to the CircleElement from where we want. It is the same with a Text in a Rectangle, we need a BlElement for the Text and another for the Rectangle in order to compose them and to position the Text in the Rectangle.
For me its like defining a CircleButton in a RectanglePanel with any other ui libraries, i can do that by subclassing Panel or by using script style. But i have to manipulate 2 elements and it makes sense for me.
Bloc does not provide user-friendly high-level abstractions at BlShape or BlElement level like BlCircleShape or BlCircleElement. I don't know if it is the right place to add them but it is clearly a point of misunderstanding when people uses Bloc.
It seems to me that Bloc is not made to be used direclty as a graphical framework but it is a librarie to build more user-friendly graphical framework. Shape, Path, ... are implementations stuff, most of users should not care about that using a "framework".
PS: @Alex, what are the planned refactoring? I'm lost in the new intentions and in the roadmap of Bloc... Regards, Glenn.
----- Glenn Cavarlé -- View this message in context: http://forum.world.st/bloc-shape-size-tp4887929p4888039.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
On 3 April 2016 at 12:27, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
However, in most UI of applications (in web, mobile) it is extremely rare that clipping or event handling areas differ from drawing one (visual one - one that user sees in the end).
A counter-example that immediately comes to mind is Pharo's icon. You could imagine a minimal version of it with just the circle/wave/splash and the striped lighthouse inside (in the current icon, that has been filled with some semi-transparent whiteish gradient). The visual shape has voids (inside the circle, in between the stripesâ¦) but the click-collision mask is basically a full disc. I'm pretty sure an early version of the icon had the same shape for rendering and click-catching, and you had to aim for the small opaque regions in it⦠-- Damien Pollet type less, do more [ | ] http://people.untyped.org/damien.pollet
On 3 April 2016 at 13:18, Denis Kudriashov <dionisiydk@gmail.com> wrote:
Hi
2016-04-03 11:08 GMT+02:00 Aliaksei Syrel <alex.syrel@gmail.com>:
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s) but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design. -- Best regards, Igor Stasenko.
On 3 April 2016 at 14:44, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 13:18, Denis Kudriashov <dionisiydk@gmail.com> wrote:
Hi
2016-04-03 11:08 GMT+02:00 Aliaksei Syrel <alex.syrel@gmail.com>:
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of
s/nothing/notion
shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
-- Best regards, Igor Stasenko.
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph. The reverse: I feel like current Morphs are huge monsters of configurability and parameter blocks and properties and intricated code and thousands of methods so that one doesn't has to subclass... Simpler, "subclassable" morphs suits me a lot better. Bloc looks like its taking some of the bad aspects of Morphic. Regards, Thierry
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com> wrote: > Le 03/04/2016 17:33, stepharo a écrit : > >> If you want to change clicking behaviour you need to override one single >> method. >> >>> >>> Everything you wrote with unreadable amount of characters is >>> for nothing. >>> >>> I see clearly point of Igor. And for me it feels very logical. >>> With such design you can lively change clipping area and >>> interaction area for any morph (element) on screen. >>> >>> >>> In short, i see only two cases where indeed, morph requires a nothing >>> of shapes to define: >>> - clipping region(s) >>> - ui interaction region(s) >>> >>> but for drawing? nooooo... really? who cares what you draw there? >>> draw anything, in any possible way you see fit.. compose, decompose, >>> recombine, blend and mix.. that's the whole purpose of drawing and be >>> artistic and be able to express yourself in any possible way you want :) >>> Why nailing and formalizing things that are tend to be hardly >>> formalizable and more than that, unnecessary. >>> That's my main concern about current design. >>> >> >> I agree. >> I do not see why people are forced to create a submorph just to change >> the rendering. >> If you want to change it dynamically you can for example pass a >> different shape. >> > > I don't see the problem with subclassing a morph. > > Me neither. But do you confusing subclassing and submorph compositing? > The reverse: I feel like current Morphs are huge monsters of > configurability and parameter blocks and properties and intricated code and > thousands of methods so that one doesn't has to subclass... > > Agree, the Morph protocol is bloated. And i don't like it too. That is a result of lifting features and properties up in inheritance chain. And i can imagine how it happens over time: - we have a morph.. - hurray! - can we have a morph with a border? - yes! Here BorderedMorph for you! - nice.. but can i use border in another subclass of Morph? - yes! Here borderStyle: property for you.. (and BorderedMorph is now useless) Or take a layout.. We could have , say, MorphWithLayout class. That introducing layouts. While other, simpler morph don't. Really, what layout you need in a morph that contains a plain rectangle fully covering its bounds? Or even 'having submorphs'. We could have MorphWithSubmorphs. Which could introduce submorphs concept. Separation of concerns. Good way to go. But if you need to have a morph that both has layout and border, then you are in trouble: you forced to do one of following: - make own Morph subclass, duplicating features of both.. or make a composition of submorphs that will represent both features, or... lift both features to the top of inheritance chain, getting bloat as result. Most of the times, most of things are achiveable through composition.. but some of them.. like drawing - apparently not. In any case i agree, that many features, that Morph proposing out of the box needs review and validation in terms, what if we isolate certain feature(s) in separate subclass and provide them via composition. Simpler, "subclassable" morphs suits me a lot better. > > Bloc looks like its taking some of the bad aspects of Morphic. > > One step at a time. You cannot fix all the problems of parent at once. The way how Bloc born, i think (i may be mistaken), it is a 'clean and lean' port of Morphic. But of course Morphic is huge monster, and porting such monster while rewriting its complex logic at the same time could be daunting hard. In any case, i think it is better. Let us hope, it will be even better. > Regards, > > Thierry > > -- Best regards, Igor Stasenko.
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:? Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
The reverse: I feel like current Morphs are huge monsters of configurability and parameter blocks and properties and intricated code and thousands of methods so that one doesn't has to subclass...
Agree, the Morph protocol is bloated. And i don't like it too. That is a result of lifting features and properties up in inheritance chain. And i can imagine how it happens over time: - we have a morph.. - hurray! - can we have a morph with a border? - yes! Here BorderedMorph for you! - nice.. but can i use border in another subclass of Morph? - yes! Here borderStyle: property for you.. (and BorderedMorph is now useless)
Or take a layout.. We could have , say, MorphWithLayout class. That introducing layouts. While other, simpler morph don't. Really, what layout you need in a morph that contains a plain rectangle fully covering its bounds? Or even 'having submorphs'. We could have MorphWithSubmorphs. Which could introduce submorphs concept.
Separation of concerns. Good way to go. But if you need to have a morph that both has layout and border, then you are in trouble: you forced to do one of following: - make own Morph subclass, duplicating features of both.. or make a composition of submorphs that will represent both features, or... lift both features to the top of inheritance chain, getting bloat as result. Most of the times, most of things are achiveable through composition.. but some of them.. like drawing - apparently not. In any case i agree, that many features, that Morph proposing out of the box needs review and validation in terms, what if we isolate certain feature(s) in separate subclass and provide them via composition.
Yes, I do think you're right.
Simpler, "subclassable" morphs suits me a lot better.
Bloc looks like its taking some of the bad aspects of Morphic.
One step at a time. You cannot fix all the problems of parent at once. The way how Bloc born, i think (i may be mistaken), it is a 'clean and lean' port of Morphic. But of course Morphic is huge monster, and porting such monster while rewriting its complex logic at the same time could be daunting hard. In any case, i think it is better. Let us hope, it will be even better.
I do hope. Certain points really require switching to Athens (sub-pixel rendering of large fonts is extremely slow), and Bloc will be the toolkit we'll have to live with. Regards, Thierry
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Did, not anymore. FTTableRowMorph>>#selectionColor: Best regards, Henrik
Le 03/04/2016 20:00, Henrik Nergaard a écrit :
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Did, not anymore.
FTTableRowMorph>>#selectionColor:
Had to check the following code to be sure: (highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ]. Was there a measurable inpact when changing that? Because I have now three ways of doing this, and all of them have trade-offs. For example the one above suppose that row items are a specific kind of Morph, i.e. FTTableRowMorph; one could do without a dedicated Morph subclass for rows and display the selection as a transparent colored rectangle over the row; this is what I do. Thierry
I changed it mostly because it was messing up the color when you did mouse-over (required to check the owner color to set it correctly when there was a selection, the code was ugly and with corner cases). Encapsulating a morph with another morph just for a background color is kind of waste IMO. Causing unnecessary overhead for rendering/layout/eventHandling etc... Mesurable? Donât think I checked, but in the long run there is less allocations, less layout etc.. I would also argue that ------------------ (highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ]. ----------------- Is better than ----------------- rowSubviews add: ((highligtedRowIndexes includes: rowIndex) ifTrue: [ "IMPORTANT: I need to set owner to nil because otherwise it will trigger an invalidation of the owner when adding morph to selectionMorph, causing an infinite loop" self toSelectionRow: (row privateOwner: nil) primary: primarySelectionIndex = rowIndex ] ifFalse: [ row ]) ]. ----------------------- Selection could be and drawn by the container, but then again you would need much more code and special logic (updating the damageRecorder with correct rectangles when selection changes for example) than to just extend and specialize one morph to be a row. I would much rather prefer one specialized morph doing its thing, than encapsulate it. Best regards, Henrik -----Original Message----- From: Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] On Behalf Of Thierry Goubier Sent: Sunday, April 3, 2016 8:58 PM To: Pharo Development List <pharo-dev@lists.pharo.org> Subject: Re: [Pharo-dev] [bloc] shape size? Le 03/04/2016 20:00, Henrik Nergaard a écrit :
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Did, not anymore.
FTTableRowMorph>>#selectionColor:
Had to check the following code to be sure: (highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ]. Was there a measurable inpact when changing that? Because I have now three ways of doing this, and all of them have trade-offs. For example the one above suppose that row items are a specific kind of Morph, i.e. FTTableRowMorph; one could do without a dedicated Morph subclass for rows and display the selection as a transparent colored rectangle over the row; this is what I do. Thierry
Hi Henrik, Le 03/04/2016 21:32, Henrik Nergaard a écrit :
I changed it mostly because it was messing up the color when you did mouse-over (required to check the owner color to set it correctly when there was a selection, the code was ugly and with corner cases).
Ok.
Encapsulating a morph with another morph just for a background color is kind of waste IMO. Causing unnecessary overhead for rendering/layout/eventHandling etc...
Rendering maybe a bit. Layout, maybe a bit. Event handling? Oh well, row morphs contents are already a tree of morphs at least 3 deep, what will be the effect of one more doing nothing?
Mesurable? Donât think I checked, but in the long run there is less allocations, less layout etc..
I guess that, given how FT works, it is hidden in the number of Morph creation per drawOn: :)
I would also argue that ------------------ (highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ]. ----------------- Is better than -----------------
rowSubviews add: ((highligtedRowIndexes includes: rowIndex) ifTrue: [ "IMPORTANT: I need to set owner to nil because otherwise it will trigger an invalidation of the owner when adding morph to selectionMorph, causing an infinite loop" self toSelectionRow: (row privateOwner: nil) primary: primarySelectionIndex = rowIndex ] ifFalse: [ row ]) ]. -----------------------
I like the game with #privateOwner: in the FT code. Tells you a lot about ownership in Morphic :) At the same time, your new code isn't very clear. It is written just as the setting of a theme property where in fact it is setting the row as selected.
Selection could be and drawn by the container, but then again you would need much more code and special logic (updating the damageRecorder with correct rectangles when selection changes for example) than to just extend and specialize one morph to be a row.
I'm doing the selection draw by container, and, honestly, there is none of the complexity you describe. Selection is a model operation anyway, so it usually triggers a redraw (because selection may move you elsewhere, if the model so chooses); if you have some caching in place (that FT hasn't), you gain a bit upon redraw, but nothing noticeable. There is another reason for moving it into the container, but that reason is not public.
I would much rather prefer one specialized morph doing its thing, than encapsulate it.
I think the FTTableRowMorph has other duties anyway, so giving him that additional role is fine. Regards, Thierry
Best regards, Henrik
-----Original Message----- From: Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] On Behalf Of Thierry Goubier Sent: Sunday, April 3, 2016 8:58 PM To: Pharo Development List <pharo-dev@lists.pharo.org> Subject: Re: [Pharo-dev] [bloc] shape size?
Le 03/04/2016 20:00, Henrik Nergaard a écrit :
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Did, not anymore.
FTTableRowMorph>>#selectionColor:
Had to check the following code to be sure:
(highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ].
Was there a measurable inpact when changing that?
Because I have now three ways of doing this, and all of them have trade-offs. For example the one above suppose that row items are a specific kind of Morph, i.e. FTTableRowMorph; one could do without a dedicated Morph subclass for rows and display the selection as a transparent colored rectangle over the row; this is what I do.
Thierry
-----Original Message----- From: Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] On Behalf Of Thierry Goubier Sent: Sunday, April 3, 2016 9:52 PM To: pharo-dev@lists.pharo.org Subject: Re: [Pharo-dev] [bloc] shape size? Hi Henrik, Le 03/04/2016 21:32, Henrik Nergaard a écrit :
I changed it mostly because it was messing up the color when you did mouse-over (required to check the owner color to set it correctly when there was a selection, the code was ugly and with corner cases).
Ok.
Encapsulating a morph with another morph just for a background color is kind of waste IMO. Causing unnecessary overhead for rendering/layout/eventHandling etc...
Rendering maybe a bit. Layout, maybe a bit. Event handling? Oh well, row morphs contents are already a tree of morphs at least 3 deep, what will be the effect of one more doing nothing?
Mesurable? Donât think I checked, but in the long run there is less allocations, less layout etc..
I guess that, given how FT works, it is hidden in the number of Morph creation per drawOn: :)
I would also argue that ------------------ (highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ]. ----------------- Is better than -----------------
rowSubviews add: ((highligtedRowIndexes includes: rowIndex) ifTrue: [ "IMPORTANT: I need to set owner to nil because otherwise it will trigger an invalidation of the owner when adding morph to selectionMorph, causing an infinite loop" self toSelectionRow: (row privateOwner: nil) primary: primarySelectionIndex = rowIndex ] ifFalse: [ row ]) ]. -----------------------
<I like the game with #privateOwner: in the FT code. Tells you a lot about ownership in Morphic :) <At the same time, your new code isn't very clear. It is written just as the setting of a theme property where in fact it is setting the row as selected. When pointing it out, I totally agree. Will fix that ;)
Selection could be and drawn by the container, but then again you would need much more code and special logic (updating the damageRecorder with correct rectangles when selection changes for example) than to just extend and specialize one morph to be a row.
<I'm doing the selection draw by container, and, honestly, there is none of the complexity you describe. Selection is a model operation anyway, so it usually <triggers a redraw (because selection may move you elsewhere, if the model so chooses); if you have some caching in place (that FT hasn't), you gain a bit upon <redraw, but nothing noticeable. No there won't be that complexity, I was thinking of mouse-over not the selection; apologies. There is another reason for moving it into the container, but that reason is not public. Ah, Yes; even/odd color difference per row.
I would much rather prefer one specialized morph doing its thing, than encapsulate it.
I think the FTTableRowMorph has other duties anyway, so giving him that additional role is fine. Regards, Thierry
Best regards, Henrik
-----Original Message----- From: Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] On Behalf Of Thierry Goubier Sent: Sunday, April 3, 2016 8:58 PM To: Pharo Development List <pharo-dev@lists.pharo.org> Subject: Re: [Pharo-dev] [bloc] shape size?
Le 03/04/2016 20:00, Henrik Nergaard a écrit :
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Did, not anymore.
FTTableRowMorph>>#selectionColor:
Had to check the following code to be sure:
(highligtedRowIndexes includes: rowIndex) ifTrue: [ row selectionColor: (self owner colorForSelection: primarySelectionIndex = rowIndex) ].
Was there a measurable inpact when changing that?
Because I have now three ways of doing this, and all of them have trade-offs. For example the one above suppose that row items are a specific kind of Morph, i.e. FTTableRowMorph; one could do without a dedicated Morph subclass for rows and display the selection as a transparent colored rectangle over the row; this is what I do.
Thierry
Best regards, Henrik
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
The reverse: I feel like current Morphs are huge monsters of
configurability and parameter blocks and properties and intricated code and thousands of methods so that one doesn't has to subclass...
Agree, the Morph protocol is bloated. And i don't like it too. That is a result of lifting features and properties up in inheritance chain. And i can imagine how it happens over time: - we have a morph.. - hurray! - can we have a morph with a border? - yes! Here BorderedMorph for you! - nice.. but can i use border in another subclass of Morph? - yes! Here borderStyle: property for you.. (and BorderedMorph is now useless)
Or take a layout.. We could have , say, MorphWithLayout class. That introducing layouts. While other, simpler morph don't. Really, what layout you need in a morph that contains a plain rectangle fully covering its bounds? Or even 'having submorphs'. We could have MorphWithSubmorphs. Which could introduce submorphs concept.
Separation of concerns. Good way to go. But if you need to have a morph that both has layout and border, then you are in trouble: you forced to do one of following: - make own Morph subclass, duplicating features of both.. or make a composition of submorphs that will represent both features, or... lift both features to the top of inheritance chain, getting bloat as result. Most of the times, most of things are achiveable through composition.. but some of them.. like drawing - apparently not. In any case i agree, that many features, that Morph proposing out of the box needs review and validation in terms, what if we isolate certain feature(s) in separate subclass and provide them via composition.
Yes, I do think you're right.
Simpler, "subclassable" morphs suits me a lot better.
Bloc looks like its taking some of the bad aspects of Morphic.
One step at a time. You cannot fix all the problems of parent at once. The way how Bloc born, i think (i may be mistaken), it is a 'clean and lean' port of Morphic. But of course Morphic is huge monster, and porting such monster while rewriting its complex logic at the same time could be daunting hard. In any case, i think it is better. Let us hope, it will be even better.
I do hope. Certain points really require switching to Athens (sub-pixel rendering of large fonts is extremely slow), and Bloc will be the toolkit we'll have to live with.
Regards,
Thierry
-- Best regards, Igor Stasenko.
Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there. In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree). A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:). Regards, Thierry
A FTTableContainerMorph recreates all its submorphs on every drawOn:. Not correct.
Submorphs are only recreated when the view of the list has changed #canRefreshValues, ie if the variable "needsRefreshExposedRows" is set to true. If this is false nothing will happen in #drawOn: If changes is necessary the drawOn: will recreate submorphs for the current view (showIndex) and set the "needsRefreshedExposedRows" to false signalling that it is correctly laid out. Best regards, Henrik -----Original Message----- From: Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] On Behalf Of Thierry Goubier Sent: Sunday, April 3, 2016 9:32 PM To: Pharo Development List <pharo-dev@lists.pharo.org> Subject: Re: [Pharo-dev] [bloc] shape size? I think FastTable is something you should have a look at. Esteban did something really interesting there. In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree). A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:). Regards, Thierry
Le 03/04/2016 21:51, Henrik Nergaard a écrit :
A FTTableContainerMorph recreates all its submorphs on every drawOn:. Not correct.
Ok. I stand corrected. This is why it is done in #drawOn: and not #drawSubmorphsOn:
Submorphs are only recreated when the view of the list has changed #canRefreshValues, ie if the variable "needsRefreshExposedRows" is set to true. If this is false nothing will happen in #drawOn:
If changes is necessary the drawOn: will recreate submorphs for the current view (showIndex) and set the "needsRefreshedExposedRows" to false signalling that it is correctly laid out.
What is interesting, still, is that submorphs rebuilding (deleting and recreating them) happens during a #drawOn: call, and that it is fast enough not to register on the time needed for a world redraw. And so I still think it is interesting for Igor to have a look at FT :) Regards, Thierry
On 3 April 2016 at 23:00, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Le 03/04/2016 21:51, Henrik Nergaard a écrit :
A FTTableContainerMorph recreates all its submorphs on every
drawOn:.
Not correct.
Ok. I stand corrected. This is why it is done in #drawOn: and not #drawSubmorphsOn:
Submorphs are only recreated when the view of the list has changed
#canRefreshValues, ie if the variable "needsRefreshExposedRows" is set to true. If this is false nothing will happen in #drawOn:
If changes is necessary the drawOn: will recreate submorphs for the current view (showIndex) and set the "needsRefreshedExposedRows" to false signalling that it is correctly laid out.
What is interesting, still, is that submorphs rebuilding (deleting and recreating them) happens during a #drawOn: call, and that it is fast enough not to register on the time needed for a world redraw.
And so I still think it is interesting for Igor to have a look at FT :)
Only for review purpose, i guess. From what you described, as i wrote in previous post this is not new to me. I think i seen some kind of morph(s) that was using same technique in the past. it may be different in details, of course, but overall idea was same: create and use as many UI elements, as many fits on the screen, not as many items in the list(s)
Regards,
Thierry
-- Best regards, Igor Stasenko.
Le 03/04/2016 22:26, Igor Stasenko a écrit :
On 3 April 2016 at 23:00, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 21:51, Henrik Nergaard a écrit :
A FTTableContainerMorph recreates all its submorphs on every drawOn:.
Not correct.
Ok. I stand corrected. This is why it is done in #drawOn: and not #drawSubmorphsOn:
Submorphs are only recreated when the view of the list has changed #canRefreshValues, ie if the variable "needsRefreshExposedRows" is set to true. If this is false nothing will happen in #drawOn:
If changes is necessary the drawOn: will recreate submorphs for the current view (showIndex) and set the "needsRefreshedExposedRows" to false signalling that it is correctly laid out.
What is interesting, still, is that submorphs rebuilding (deleting and recreating them) happens during a #drawOn: call, and that it is fast enough not to register on the time needed for a world redraw.
And so I still think it is interesting for Igor to have a look at FT :)
Only for review purpose, i guess. From what you described, as i wrote in previous post this is not new to me. I think i seen some kind of morph(s) that was using same technique in the past. it may be different in details, of course, but overall idea was same: create and use as many UI elements, as many fits on the screen, not as many items in the list(s)
Yes, probably. Regards, Thierry
On 3 April 2016 at 22:32, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com
<mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing
background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there.
In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree).
Sounds like right way to do it. There's no point to keep million UI elements for million items in list, since you never render them all at once on the screen. So, practical approach is to create as many UI elements as fits on the screen, but not as many you have in list.
A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:).
Yeah, i did similar thing in TxText - also create morph(s) only for part of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of text, the portion that currently displayed, but never for whole text, which can be megabytes long. Thus, it guarantees that overall performance are bound to the area, covered by UI control that displays the text, but not to text size.
Regards,
Thierry
-- Best regards, Igor Stasenko.
On 03 Apr 2016, at 21:58, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 22:32, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote: Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>
<mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there.
In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree).
Sounds like right way to do it. There's no point to keep million UI elements for million items in list, since you never render them all at once on the screen. So, practical approach is to create as many UI elements as fits on the screen, but not as many you have in list.
I think that Cocoa list does that. When a list item goes out of the screen itâs sent to a pool, and when a new one has to be displayed they take any one from that pool and re-initialize.
A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:).
Yeah, i did similar thing in TxText - also create morph(s) only for part of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of text, the portion that currently displayed, but never for whole text, which can be megabytes long. Thus, it guarantees that overall performance are bound to the area, covered by UI control that displays the text, but not to text size.
Regards,
Thierry
-- Best regards, Igor Stasenko.
Le 03/04/2016 21:58, Igor Stasenko a écrit :
On 3 April 2016 at 22:32, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>
<mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there.
In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree).
Sounds like right way to do it. There's no point to keep million UI elements for million items in list, since you never render them all at once on the screen. So, practical approach is to create as many UI elements as fits on the screen, but not as many you have in list.
A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:).
Well, as Henrik pointed out, not everytime ;)
Yeah, i did similar thing in TxText - also create morph(s) only for part of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of text, the portion that currently displayed, but never for whole text, which can be megabytes long. Thus, it guarantees that overall performance are bound to the area, covered by UI control that displays the text, but not to text size.
I'm interested to know how you handle scrolling then: how do you define the step, the length and the position: relative to the number of characters displayed / start character of the current UI / and knowing the number of characters in the whole text, so that you are independent of the layout? Regards, Thierry
On 3 April 2016 at 23:30, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Le 03/04/2016 21:58, Igor Stasenko a écrit :
On 3 April 2016 at 22:32, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>
<mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there.
In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree).
Sounds like right way to do it. There's no point to keep million UI elements for million items in list, since you never render them all at once on the screen. So, practical approach is to create as many UI elements as fits on the screen, but not as many you have in list.
A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:).
Well, as Henrik pointed out, not everytime ;)
Yeah, i did similar thing in TxText - also create morph(s) only for part
of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of text, the portion that currently displayed, but never for whole text, which can be megabytes long. Thus, it guarantees that overall performance are bound to the area, covered by UI control that displays the text, but not to text size.
I'm interested to know how you handle scrolling then: how do you define the step, the length and the position: relative to the number of characters displayed / start character of the current UI / and knowing the number of characters in the whole text, so that you are independent of the layout?
The scroll is defined in delta in pixels. So, scrolling single line - you scroll by top or bottom line height (depending on direction). Scrolling page - you scroll by using height of viewport. No need to count lines of text. And so, i scan text forward or backward until new layout fully covers part of text after such scrolling. And after it deleting portion of layout that became invisible due to scrolling. The layout has anchor point in text - a position. And then dimensions (width and height) and offset (a delta horizontal or vertical relative to perfect condition when a position in text corresponds to 0,0 point in layout ) The only place where i needed to measure text size was to positioning a scrollbar knob to represent its size & vertical position approximately close to where you in text and text size. And i really don't like that, since it requires scanning whole text.. But well... tradeoffs.. It win anyways, since i succeeded to avoid most operations to be bound to text size. And only few left, that you cannot avoid. Regards,
Thierry
-- Best regards, Igor Stasenko.
On 3 April 2016 at 23:41, Igor Stasenko <siguctua@gmail.com> wrote:
On 3 April 2016 at 23:30, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Le 03/04/2016 21:58, Igor Stasenko a écrit :
On 3 April 2016 at 22:32, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>
<mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there.
In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree).
Sounds like right way to do it. There's no point to keep million UI elements for million items in list, since you never render them all at once on the screen. So, practical approach is to create as many UI elements as fits on the screen, but not as many you have in list.
A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:).
Well, as Henrik pointed out, not everytime ;)
Yeah, i did similar thing in TxText - also create morph(s) only for part
of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of text, the portion that currently displayed, but never for whole text, which can be megabytes long. Thus, it guarantees that overall performance are bound to the area, covered by UI control that displays the text, but not to text size.
I'm interested to know how you handle scrolling then: how do you define the step, the length and the position: relative to the number of characters displayed / start character of the current UI / and knowing the number of characters in the whole text, so that you are independent of the layout?
The scroll is defined in delta in pixels. So, scrolling single line - you scroll by top or bottom line height (depending on direction).
Or maybe i lying here.. i could be 'scroll up/down' until next/previous line are fully visible in layout. (There's of course an edge case, when line height is bigger than viewport height)
Scrolling page - you scroll by using height of viewport. No need to count lines of text. And so, i scan text forward or backward until new layout fully covers part of text after such scrolling. And after it deleting portion of layout that became invisible due to scrolling.
The layout has anchor point in text - a position. And then dimensions (width and height) and offset (a delta horizontal or vertical relative to perfect condition when a position in text corresponds to 0,0 point in layout )
The only place where i needed to measure text size was to positioning a scrollbar knob to represent its size & vertical position approximately close to where you in text and text size. And i really don't like that, since it requires scanning whole text.. But well... tradeoffs.. It win anyways, since i succeeded to avoid most operations to be bound to text size. And only few left, that you cannot avoid.
Regards,
Thierry
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Le 03/04/2016 22:46, Igor Stasenko a écrit :
On 3 April 2016 at 23:41, Igor Stasenko <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote:
On 3 April 2016 at 23:30, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 03/04/2016 21:58, Igor Stasenko a écrit :
On 3 April 2016 at 22:32, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> wrote:
Le 03/04/2016 20:01, Igor Stasenko a écrit :
On 3 April 2016 at 20:51, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>>> wrote:
Le 03/04/2016 19:12, Igor Stasenko a écrit :
On 3 April 2016 at 19:48, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>
<mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com> <mailto:thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>>>> wrote:
Le 03/04/2016 17:33, stepharo a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
I see clearly point of Igor. And for me it feels very logical. With such design you can lively change clipping area and interaction area for any morph (element) on screen.
In short, i see only two cases where indeed, morph requires a nothing of shapes to define: - clipping region(s) - ui interaction region(s)
but for drawing? nooooo... really? who cares what you draw there? draw anything, in any possible way you see fit.. compose, decompose, recombine, blend and mix.. that's the whole purpose of drawing and be artistic and be able to express yourself in any possible way you want :) Why nailing and formalizing things that are tend to be hardly formalizable and more than that, unnecessary. That's my main concern about current design.
I agree. I do not see why people are forced to create a submorph just to change the rendering. If you want to change it dynamically you can for example pass a different shape.
I don't see the problem with subclassing a morph.
Me neither. But do you confusing subclassing and submorph compositing?
Let me return you the question then: do you do a composition of submorphs if you're trying to get a different drawOn:?
Who, me? No. Maybe i was just misunderstood your reply. Because what i was tried to demonstrate in previous post(s) that there's simply no easy way to expose all possible drawing operations via composition of morphs (or composition of any other kind of elements), unless, of course you will lift full feature set of Athens to the level of composition.. As result you will get a full feature set that Athens provides, plus extra complexity. Sounds like thing to do, no? :)
Agreed :)
Oh, ok, that's true FastTable does it for the selection... changing background color by encapsulating a row in another Morph with the right background color.
Well, i don't know what is FastTable beast are.. so i cannot comment on this one.
I think FastTable is something you should have a look at. Esteban did something really interesting there.
In FT, Submorphs are only created when they are about to be displayed: Pharo can easily create hundreds of morphs on every redraw cycle. So FT performance is O(k) where k is the number of rows to display on screen (typical k is ~25), and is O(1) regarding the length of the list (almost: there is a point, for very large tree-like structures, where just iterating over the structure becomes the main performance limitation: see FTTree).
Sounds like right way to do it. There's no point to keep million UI elements for million items in list, since you never render them all at once on the screen. So, practical approach is to create as many UI elements as fits on the screen, but not as many you have in list.
A FTTableContainerMorph recreates all its submorphs on every drawOn:. I've played with different variants (do not recreate all submorphs, for example) but you don't see any performance difference (on the time needed for a drawOn:).
Well, as Henrik pointed out, not everytime ;)
Yeah, i did similar thing in TxText - also create morph(s) only for part of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of text, the portion that currently displayed, but never for whole text, which can be megabytes long. Thus, it guarantees that overall performance are bound to the area, covered by UI control that displays the text, but not to text size.
I'm interested to know how you handle scrolling then: how do you define the step, the length and the position: relative to the number of characters displayed / start character of the current UI / and knowing the number of characters in the whole text, so that you are independent of the layout?
The scroll is defined in delta in pixels. So, scrolling single line - you scroll by top or bottom line height (depending on direction).
You wrote a dedicated scrollbar? The standard one is [0, 1.0] with a constant step whatever the direction so it's hard to make the difference in height between the top line or the bottom line. But it could be worth subclassing ScrollBar for that purpose.
Or maybe i lying here.. i could be 'scroll up/down' until next/previous line are fully visible in layout. (There's of course an edge case, when line height is bigger than viewport height)
That edge case is complex to handle...
Scrolling page - you scroll by using height of viewport. No need to count lines of text. And so, i scan text forward or backward until new layout fully covers part of text after such scrolling. And after it deleting portion of layout that became invisible due to scrolling. The layout has anchor point in text - a position. And then dimensions (width and height) and offset (a delta horizontal or vertical relative to perfect condition when a position in text corresponds to 0,0 point in layout )
Understood for the scan forward or backward.
The only place where i needed to measure text size was to positioning a scrollbar knob to represent its size & vertical position approximately close to where you in text and text size. And i really don't like that, since it requires scanning whole text.. But well... tradeoffs.. It win anyways, since i succeeded to avoid most operations to be bound to text size. And only few left, that you cannot avoid.
What do you scan in the text? Do you compute a complete pixel height of the text or some approximation? Thanks, Thierry
On 4 April 2016 at 00:18, Thierry Goubier <thierry.goubier@gmail.com> wrote:
The scroll is defined in delta in pixels. So, scrolling single line - you scroll by top or bottom line height (depending on direction).
You wrote a dedicated scrollbar? The standard one is [0, 1.0] with a constant step whatever the direction so it's hard to make the difference in height between the top line or the bottom line.
Yes. I, of course did not made it dedicated only for text. But i guess text is only single user of it so far.
But it could be worth subclassing ScrollBar for that purpose.
Unfortunately, my cognitive capacity was not that high at that moment, in order to understand how ScrollBar is working and what needs to be done in order to adapt it to my text model. Or maybe because when i was looking at its implementation the only thing i was thinking is not to run screaming in terror. Pick one explanation, that suits you best :)
Or maybe i lying here.. i could be 'scroll up/down' until next/previous
line are fully visible in layout. (There's of course an edge case, when line height is bigger than viewport height)
That edge case is complex to handle...
Scrolling page - you scroll by using height of viewport. No need to
count lines of text. And so, i scan text forward or backward until new layout fully covers part of text after such scrolling. And after it deleting portion of layout that became invisible due to scrolling. The layout has anchor point in text - a position. And then dimensions (width and height) and offset (a delta horizontal or vertical relative to perfect condition when a position in text corresponds to 0,0 point in layout )
Understood for the scan forward or backward.
The only place where i needed to measure text size was to
positioning a scrollbar knob to represent its size & vertical position approximately close to where you in text and text size. And i really don't like that, since it requires scanning whole text.. But well... tradeoffs.. It win anyways, since i succeeded to avoid most operations to be bound to text size. And only few left, that you cannot avoid.
What do you scan in the text? Do you compute a complete pixel height of the text or some approximation?
Well, for scrollbars it is just counting lines of text. For layout , it is of course, fully precise text layout & kerning yadda yadda.
Thanks,
Thierry
-- Best regards, Igor Stasenko.
Le 03/04/2016 23:31, Igor Stasenko a écrit :
On 4 April 2016 at 00:18, Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
The scroll is defined in delta in pixels. So, scrolling single line - you scroll by top or bottom line height (depending on direction).
You wrote a dedicated scrollbar? The standard one is [0, 1.0] with a constant step whatever the direction so it's hard to make the difference in height between the top line or the bottom line.
Yes. I, of course did not made it dedicated only for text. But i guess text is only single user of it so far.
Ok.
But it could be worth subclassing ScrollBar for that purpose.
Unfortunately, my cognitive capacity was not that high at that moment, in order to understand how ScrollBar is working and what needs to be done in order to adapt it to my text model. Or maybe because when i was looking at its implementation the only thing i was thinking is not to run screaming in terror.
:)
Pick one explanation, that suits you best :)
I'm using the same explanation when I see some widgets. I wanted to use a button for expand/unexpand in a tree, looked at the variants of ButtonMorphs (and three state button morphs and...), got a headache and just took a normal Morph with a custom handler :(
Or maybe i lying here.. i could be 'scroll up/down' until next/previous line are fully visible in layout. (There's of course an edge case, when line height is bigger than viewport height)
That edge case is complex to handle...
Scrolling page - you scroll by using height of viewport. No need to count lines of text. And so, i scan text forward or backward until new layout fully covers part of text after such scrolling. And after it deleting portion of layout that became invisible due to scrolling. The layout has anchor point in text - a position. And then dimensions (width and height) and offset (a delta horizontal or vertical relative to perfect condition when a position in text corresponds to 0,0 point in layout )
Understood for the scan forward or backward.
The only place where i needed to measure text size was to positioning a scrollbar knob to represent its size & vertical position approximately close to where you in text and text size. And i really don't like that, since it requires scanning whole text.. But well... tradeoffs.. It win anyways, since i succeeded to avoid most operations to be bound to text size. And only few left, that you cannot avoid.
What do you scan in the text? Do you compute a complete pixel height of the text or some approximation?
Well, for scrollbars it is just counting lines of text. For layout , it is of course, fully precise text layout & kerning yadda yadda.
Understood. Thanks again for all the explanations. Thierry
On 03-04-16 21:58, Igor Stasenko wrote:
Yeah, i did similar thing in TxText - also create morph(s) only for > part of text which is currently displayed.. and basically it is same idea for TxText itself: it calculates layout only for a portion of > text, the portion that currently displayed, but never for whole > text, which can be megabytes long. Thus, it guarantees that overall > performance are bound to the area, covered by UI control that > displays the text, but not to text size.
Which, if I understand it correctly, works fine for code editing, but does not cover the needs of high-quality typesetting like we might want in pillar rendering or advanced word processing. Systems like TeX, Framemaker and InDesign need to recompute layout back to the beginning of a hard page/column break, like a new chapter, and page numbering requires whole document recomputation, as references to page numbers in the text get a new width. Most documents have enough spacing margin that the recomputation does not propagate so far as to have a user noticable impact. I used Framemaker version from version 5, and that was able to do so with acceptable speed in 1995. 20 years of CPU improvements should allow us to do the same in Smalltalk Stephan
On 4 April 2016 at 10:47, Stephan Eggermont <stephan@stack.nl> wrote:
On 03-04-16 21:58, Igor Stasenko wrote:
Yeah, i did similar thing in TxText - also create morph(s) only for > part of text which is currently displayed.. and basically it is same
idea for TxText itself: it calculates layout only for a portion of > text, the portion that currently displayed, but never for whole > text, which can be megabytes long. Thus, it guarantees that overall > performance are bound to the area, covered by UI control that > displays the text, but not to text size.
Which, if I understand it correctly, works fine for code editing, but does not cover the needs of high-quality typesetting like we might want in pillar rendering or advanced word processing. Systems like TeX, Framemaker and InDesign need to recompute layout back to the beginning of a hard page/column break, like a new chapter, and page numbering requires whole document recomputation, as references to page numbers in the text get a new width. Most documents have enough spacing margin that the recomputation does not propagate so far as to have a user noticable impact. I used Framemaker version from version 5, and that was able to do so with acceptable speed in 1995. 20 years of CPU improvements should allow us to do the same in Smalltalk
Well, the changes to text and amount of (re)computations they triggering was out of the scope of our discussion. Yes, indeed this is possible to do with acceptable speed. But in addition to that, TxText was never thought as a base for full-fledged word processing. There's no model for paper-press era things, like page numbers, chapters, columns etc. Its primary focus is to support displaying text in our UI and overcome shortcomings of old model. Since most of text is source code and for code editing, not a surprise that most features was prioritized accordingly around that fact. Frankly i don't think we need to focus on making yet another all-doing, all-knowing word processor. First, it is huge investment of workforce and time, and second - it is investment with no return or infinitelysmall marginal return. Apart from being 'cool to have', full-fledged word processing is not a thing, that you dealing with on a daily basis in environment, like Pharo. Stephan
-- Best regards, Igor Stasenko.
Sorry aliaksei but this is not an anwser in a discussion Le 3/4/16 11:08, Aliaksei Syrel a écrit :
If you want to change clicking behaviour you need to override one single method.
Everything you wrote with unreadable amount of characters is for nothing.
All mentioned stuff is possible.
On Apr 3, 2016 10:30 AM, "Igor Stasenko" <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote:
On 3 April 2016 at 10:18, Tudor Girba <tudor@tudorgirba.com <mailto:tudor@tudorgirba.com>> wrote:
Hi Igor,
Thanks for this nice description :).
Indeed, the Shape in Bloc is primarily a clipping shape that knows how to draw the path around and to fill itself. Of course, it also handles the interaction.
When you want to have a composition, you are encouraged to create multiple elements (morphs). This is a way to handle both more complicated interaction and more complicated drawing. Of course, you can still override the drawing method and draw whatever you want on it, but we would rather have a simple composition.
The disadvantage of this design is that indeed, is that it is not sophisticated. The advantage of this design is that it is not sophisticated :) and you get only one tree of compositions for the elements without another level of composition at the shape level. The main reason we went this route is because we want Bloc to pose as little constraints for the things built on top as possible without losing power.
Does this make sense for you?
It makes sense, sure thing. But it does not solves the problem. As i explained before, a single shape cannot serve as both clipping, UI handling and drawing all together. Because it is three separate roles, which is good if they coincide, but causing a lot of problems, when they are not. It is not matters how you compose or decompose shapes.. there is simply no composition which can turn rectangle into, lets say circle. it simply impossible to construct required clipping shape, or UI shape from set of drawing shapes, in case when they are completely different from each other.
For instance if i want morph with rectangular appearance (rectangle shape) to respond on clicks only within circular subregion inside that rectangle, i will be forced to create a submorph and then rewire event handling back to its parent. And that happens every time i need a different shape for mouse clicks than shape for drawing. Now add clipping here... and you will get a nightmare of bells and whistles, composing and whatsnot.
As for 'sophisticated'.. let see: so, in my proposition, i do: - draw rectangle and circle inside - define that circle as UI shape - define that rectangle as clipping shape done. In your design, i have to: - make a morph with rectangular shape - create submorph with circular shape - wire clicking of a submorph to propagate event to its parent
or think about some kind of composition.. composing what with what? does it union of circle and rectangle? or intersection? depending the way how you composing those two shapes you receive one or another outcome.. and that event wiring is extra work.. So, it may look that what i proposing is more sophisticated.. But i just wanna see a separate roles taking own places, nothing else. I do not inventing new concepts, that wasn't there before: - you need clipping, - you need drawing - you need UI handling
You see, it is not a framework, that forcing you to be 'sophisticated' .. it is domain itself. It draws a clear border between things that are optional and things that are absolutely necessary, since they are separate concepts and roles.
You simply cannot represent an infinite dimension of drawing compositions by a composition of UI elements. Only the simplest cases.. It is big mistake to imply that anything that you drawing on screen must be a full-blown UI element (which is morph is) or their composition. It makes you quite limited in terms of what you can draw and what not. Morph is UI building brick.. but it is not graphical building brick.. making such parallel gives more troubles than it solves.
To me concept where morph==shape==clipping shape==ui shape is just: - you can have bike of any color, as long as it's black.
Can you enlighten me, what composition of black bikes can result in a green one?
Cheers, Doru
> On Apr 3, 2016, at 6:38 AM, Igor Stasenko <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote: > > Oh, yeah.. i missed one more kind of shape, you may want to introduce: > - clipping shape. > > For optimizing drawing operations, you may want to define a region, which guarantees, that anything you paint, nothing outside defined region will affect the screen. Because else, you will allow morph to render anywhere and therefore, it is really hard for UI subsystem to account damage on the screen. > But once you define such shape, then you can clearly tell, which portion of the screen may or may not be damaged and therefore act accordingly. > > So, overall when we talking about shapes, we need to talk about three different kinds of them: > > - UI interaction shape > - clipping shape > - shape(s) used to draw > > those three may or may not coincide into single one, depending on complexity and what you wanna do.. > But they can be completely different from each other and in order to avoid confusion and frustration, i would really introduce them in such manner, that users have clear vision on what happens with their morphs and how to achieve what they want. > > Clearly, a single #shape: is not enough, if you want a non-conflicting representation of these concepts in UI. > > > On 3 April 2016 at 07:15, Igor Stasenko <siguctua@gmail.com <mailto:siguctua@gmail.com>> wrote: > > > On 2 April 2016 at 20:59, stepharo <stepharo@free.fr <mailto:stepharo@free.fr>> wrote: > > > Le 2/4/16 17:31, Aliaksei Syrel a écrit : >> You don't want to draw a shape, you configure it. Shape can not be drawn, it is not an AthensPath. >> >> cell shape: (BlShape new >> path: BlCirclePath new; >> strokePaint: (BlStrokePaint new >> paint: Color blue; >> width: 1)). >> cell extent: 50@50. >> > > But this is not what I want! As I mentioned in a mail that was sent but never arrived. > I want a square and this is why I did > > BlCell>>initialize > super initialize. > self > shape: > (BlShape new > fillPaint: (BlColorPaint new color: (Color yellow)); > path: BlRectanglePath new); > extent: self extent > > > then I want to draw something extra this is why I overrode drawOnAthensCanvas: aCanvas > > Now I stop but I find bloc too complex. > > Sorry but I cannot lose time like that and just get frustrated at the end. > I will use the athens canvas directly and stay in morph for now. > > > I think there's a bit of misconception. > In Athens, shape representing any area you wanna fill with paint. Period. > It can be of any complexity, self-intersecting yadda yadda.. the main point is that it defines a region(s), that going to be filled with chosen paint during draw operation. > From perspective of morphs, as UI elements, most of them require some shape(s) to represent themselves on the screen. But there are morphs, that while still taking part in UI, don't need any shapes since they never drawn on the screen. > Another point is that nowhere said that morph can be represented by a one and only one shape period. Because as in your case, you want to, say, draw rectangle with paint A, and circle with paint B, then you basically need two different shapes (overlapping or not - not really matters) to represent morph on the screen. > > So, the first point in misconception comes from 'self shape:'.. > It is wrong from that perspective, because it is all fine, when morph using only single shape to represent itself.. but when you need multiple shapes, you are in trouble. It at least misleading, because provoking you to think that there can be only one. > > Then you need to invent a 'composite shape' that basically a collection of shapes for a single morph, that will represent it on the screen. > > A tangent to that, is that since most of morphs has mostly static geometry/topology and changing it very rarely and much less often comparing to drawing same shape(s) over and over again, it is right thing to define and initialize shape(s) and reuse them later in #draw method. Since you don't change shape(s), you don't have to generate new object(s). > From that perspective, this is nice, resource saving, approach. > But let us not forget, that this is just a 'statistical observation' and hence good to be a default setup. But it should not dictate you the rule(s). > You should still be able to define shape(s) on the fly or change it on the fly, dynamically. > > Another problematic is that you may want to use different shapes for > a) painting morph on screen > b) defining geometry of the morph for UI interactions. > As an example, let say, you want a rectangle with circle in centre on the screen, but also want morph to react on mouse over/clicks only if mouse cursor is inside a circle, but not when it's over an area covered by rectangle. > > What it means, that from UI perspective, you want from morph to define its shape, lets call it 'UI interaction shape'.. and from that perspective 'self shape:' is a good choice. But as example says, it has nothing to do with 'drawing shape(s)', which may or may not coincide with shape you using for UI interaction(s). > > Because it defines an area, where UI stuff could happen. And indeed, you really need one, and only one. You don't need multiple shapes there, since it serves to answer a simple question: 'are my mouse in interesting region or not'?. > Like in your case, when you having box with circle inside , which is two shapes, but only one shape that can define an interesting region, it could be: > - intersection of > - union > - subtraction > > And that could be completely different from shape(s) you may need to draw it on the screen. > > Stef > >> On Apr 2, 2016 4:57 PM, "stepharo" <stepharo@free.fr <mailto:stepharo@free.fr>> wrote: >> Hi >> >> I want a square morph with a circle or a line at 45 degree inside >> Now I do not get it. >> >> I thought that I needed to specialize drawOnAthensCanvas: so I did >> >> BlCell >> drawOnAthensCanvas: aCanvas >> >> super drawOnAthensCanvas: aCanvas. >> aCanvas >> drawShape: (BlShape new >> strokePaint: >> (BlStrokePaint new >> paint: (BlColorPaint new color: (Color blue)); >> width: 15); >> path: BlCirclePath new). >> >> Now I do not know how I can specify a shape size >> >> So I will use another API than drawShape: >> >> Stef >> > > > > > -- > Best regards, > Igor Stasenko. > > > > -- > Best regards, > Igor Stasenko.
-- www.tudorgirba.com <http://www.tudorgirba.com> www.feenk.com <http://www.feenk.com>
"Reasonable is what we are accustomed with."
-- Best regards, Igor Stasenko.
2016-04-02 16:56 GMT+02:00 stepharo <stepharo@free.fr>:
Hi
I want a square morph with a circle or a line at 45 degree inside Now I do not get it.
I thought that I needed to specialize drawOnAthensCanvas: so I did
BlCell >> drawOnAthensCanvas: aCanvas
super drawOnAthensCanvas: aCanvas. aCanvas drawShape: (BlShape new strokePaint: (BlStrokePaint new paint: (BlColorPaint new color: (Color blue)); width: 15); path: BlCirclePath new).
Can it be implemented by special kind of BiPath? it will draw rectangle and circle inside.
participants (11)
-
Aliaksei Syrel -
Damien Pollet -
Denis Kudriashov -
Glenn Cavarlé -
Henrik Nergaard -
Igor Stasenko -
Stephan Eggermont -
stepharo -
Thierry Goubier -
Tudor Girba -
Yuriy Tymchuk