Thanks for this reply, Alex. Doru
On Mon, Mar 23, 2015 at 8:54 PM, Aliaksei Syrel <[email protected]> wrote: > Hi, > > Sorry if my reply will be too long, but I tried to summarise our > experience with Morphic/Brick and give some useful feedback or even provide > ideas. Who wants will read :) > > Brick is not a thin layer anymore. > > It depends on what you mean under 'a thin layer' ;) Anyway, Brick was born > out of need. Spotter is completely built using Brick and Rubric. No morphs > are used at all (except Rubric of course). All Bricks in Spotter in the end > are subclasses of GLMBrick, which uses from original Morph only Canvas > (without drawing) and MorphicEvents. Everything else was rewritten from > scratch. During some period of time Brick was able to render itself on > Athens canvas, but we dropped it because of Font issues in athens. > Spotter is not the only tool written using Brick, GLMPager - a pane pager > in GT-Inspector, GT-Playground and GT-Debugger is also completely done > using Brick. Almost all tab labels and tab selector in GT tools are Bricks. > > I could say that we collected quite some experience building it. Now I > would like to enumerate features of UI framework we used to solve > encountered problems. > > > - Local bound coordinates. > > Nothing to say more here :) It's somehow obvious to have. > > > - Detects graph of Bricks that should be invalidated when Brick > triggers invalidation. So there is no need to invalidate the whole graph. > - For example if Brick fills parent it means that it doesn't depend > on children (simple and most common situation). So if any child triggers > invalidation there is no need to invalidate parent as it doesn't depend > on > them. The same works in reversed way. > - Build graph separately for each dimension: width and height. If > only height of Brick was changed and children depend only on width, > there > is no need to invalidate them => x2 faster. > - Invalidate resizing and re layouting separately. If there is no > need to reposition bricks when size changes we just skip it. > > > - Link subbricks in a DoubleLinked list. So subbrickAfter and > subbrickBefore could be done in O(1). Morphic does it in O(n). It iterates > over the whole submorphs collection of the owner finds index if current > morph and then returns submorphs at: index +/-1. submorphAfter is used when > morphic tries to detect which morph should take focus. Take a look at: > Morph>>nextMorphWantingFocus. It iterates over owner's subbricks and for > each asks submorphAfter (O(n)) - resulting time O(n^2)! That is why opening > a window with a lot of submorphs takes so many time, especially system > browser for big classes. > > > - Native support of *paddings* with css-like syntax: > > padding: anArrayOrInteger > > paddingTop: anInteger >> paddingRight: anInteger >> paddingBottom: anInteger >> paddingLeft: anInteger > > > padding: 10. "top, right, bottom, left padding are 10px" > > padding: #(10 20). "top, bottom padding 10px. left, right padding 20px" > > padding: #(10 20 30). "top 10px. left, right 20px. bottom 30px" > > padding: #(10 20 30 40). "top 10px, right 20px, bottom 30px, left 40px" > > > - Native support of *margins* with css-like syntax: > > margin: anArrayOrInteger > > marginTop: anInteger >> marginRight: anInteger >> marginBottom: anInteger >> marginLeft: anInteger > > Have the same syntax as padding. > > > - Native support of dynamic *minHeight, minWidth, maxHeight, maxWidth* > > minWidth: anIntegerOrBlock "actually any object that implements >> brickValue:" >> maxHeight: anIntegerOrBlock > > > minHeight: [ : brick | brick label width * 2 ]. > > minHeight: 200. > > maxWidth: [ self height / 2 ]. > > maxWidth: 100. > > > - Native support of *z-index*, so we don't rely on subbricks' order > any more if one brick should be drawn above/below others. Works the same as > css one. > > zIndex: 2. "default value is 1" > > > > - Native support of *floating *bricks. Floating bricks don't > influence on any other neighbour bricks in layout. > > floating: aSymbol > > floating: #right. "top right brick's corner matches top right parent's > corner + corresponding paddings and margins" > > floating: #center. "will be in the center of the parent and doesn't care > about other subbricks" > > Example use case is scroll bar in spotter - it has floating: #right and > zIndex: 2 so it appears above all list elements. (+ some margins to make it > fancy). > > > - Native support of horizontal and vertical *aligning*. > > hAlign: aSymbol > > vAlign: aSymbol > > hAlign: #right. > > vAlign: #center. > > > > - Horizontal and vertical *shrinking* to fit children. It is possible > to have in one brick two subbricks where one shrink wraps and other fills > parent. > > hShrinkWrap. >> vShrinkWrap. > > > > - Horizontal and vertical *filling* with support of percents and > min/max height/width. If in brick one child shrink wraps width (or have > static width) and other fills 100% of parent's width, filling one will take > only available space left by shrinking (or static) brick. > > hSpaceFill: aFloat - fills aFloat percents of parent's width >> hSpaceFill. - alias for 100 percents. >> vSpaceFill: aFloat - fills aFloat percents of parent's height >> vSpaceFill. - alias for 100 percents. > > > > - Transparent *border* styling with possibility to separately > configure each side. > > borderWidth: anArrayOrInteger. >> borderColor: anArrayOrColor > > The same syntax as used for paddings/margins > > > - Native support of smooth gradient *box-shadows* with rounded corners: > > shadowColor: aColor. >> shadowWidth: anInteger. > > > > - Layout events such as: > > onLayouted - "called when brick was completely resized and layouted in >> its parent" > > onChildrenLayouted - "called when all children are completely resized and >> layouted" > > > Use case: implementing flexible and responsive UI. Used in GLMLabelBrick > to shrink text and add '...' when it doesn't fit in parent. Example is tab > labels in Playground. Morphic version of tabs shrinks text and change ui of > the tab during drawing. WAT? > > > - Application dependent themes. To make app work perfect all UI > elements should have the same style. In case of spotter, item preview is > created outside of spotter and there is no way using existing morph theme > mechanism to customize its look&feel especially for spotter, because > widgets always refer to global UITheme. Brick extends theming mechanism and > allows to extend existing themes specifically for needed application and it > will be applied to the whole tree of subbricks. For example spotter can > completely change theme in runtime to dark (without even closing it). > > "in context of SpotterMorph" self themer: GTSpotterBrickDarkThemer new. >> (or just replace first line in initialize) > > Even having white theme chosen in settings. (all rubric fields become dark > too). > > > > - What we really want to have in Bloc is an easy way to detect that > user clicked outside of specific morph. > > > What do you want with brick ? A new framework or just an "implementation >> detail" for spotter? >> It is *really* important to clarify this. > > > Now it becomes more stable, api changes less and less. We already have > quite a number of tests for layouting logic and documentation for basic > widgets. > What we want from brick... I think we want to have a way to build fast and > cheap unique and complex UIs. While it will fit our needs in GT Team we > will use it. We really would like to move all tools to Bloc as soon as > possible, but we just need something right now that works and can be used > in current version. Of course it would be great to cooperate to make Bloc > release sooner. > > Some time ago I tried to port Brick on top of Bloc saving all business > logic untouched and only changing events from morphic ones to bloc and > FormCanvas to AthensCanvas. It was rather successful. I will be happy if it > would be possible to do everything or almost everything mentioned above in > Bloc. I think we will never (but who knows) announce Brick as separate > project. In our minds it is just useful helper library. > > Thanks for reading :) > > Cheers, > Alex > -- www.tudorgirba.com "Every thing has its own flow"
