pharo-graphics / Bloc

Low-level UI infrastructure & framework for Pharo
MIT License
81 stars 40 forks source link

[Question] Use of `BlSpace` #12

Closed darth-cheney closed 7 years ago

darth-cheney commented 7 years ago

Preface: I would like to help out with commenting, documentation, and experimentation when it comes to Bloc and -- if possible -- Brick.

For now I'm trying to get a sense of how everything fits together.

This brings me to a question about BlSpace. Is it correct that all BlElements must be inside of a BlSpace in order to be displayed? Currently BlSpace will open a new SystemWindow in order to accomplish this -- is this because BlSpace is designed to eventually replace the Morphic World and therefore we temporarily need something to display BlElements inside of?

Shorter version: Is it possible to display a BlElement outside of a window at this time?

syrel commented 7 years ago

Hi

Is it possible to display a BlElement outside of a window at this time?

The goal for us was to make Bloc independent from morphic. Initial versions of Bloc were compatible with morphs: users could add bloc elements to morphs and the way around. This approach lead us to increased code complexity and forced to change architecture of bloc (keep it ugly) in order to present morph <-> bloc compatibility. So, there is no way to add Bloc elements to morphic World as direct children.

Is it correct that all BlElements must be inside of a BlSpace in order to be displayed?

What do you mean by "to be displayed"? Any bloc element can be previewed in Inspector out of box without the need to add it to a Space:

screen shot 2017-03-16 at 17 13 11

Additionally, any Bloc element can be converted (rendered) to a Form and displayed in the World:

screen shot 2017-03-16 at 17 16 37

The problem with this approach is that elements can not receive events, since BlSpace is responsible for dispatching user events.

So we come to the next question, how and more important from where to get user events? To solve this problem Bloc offers so called Hosts (BlHost). BlHost is an abstract class that defines api that is used by BlSpace to communicate with native multimedia APIs. At this point default Host is BlocHost-Morphic. It can be changed in Settings > Appearance > Bloc. Unfortunately, it is the only Host that works with latest VM. SDL2 host only works with VM #497. Additionally we have OSWIndow and GTK3 hosts that are under developments.

syrel commented 7 years ago

Space can be asked to be borderless by sending borderless: true:

screen shot 2017-03-16 at 17 29 57
darth-cheney commented 7 years ago

Excellent, thanks. That's all great information. One further question: if I want to add some functionality, or some type of new BlElement, or some type of Brick or other component, is there a hard and fast rule about accessing Sparta objects? IE, should Sparta ONLY ever be accessed within a Bloc or Bloc descendant? I just want to keep the patterns sane

syrel commented 7 years ago

is there a hard and fast rule about accessing Sparta objects?

Yes, a rule is simple: never ever hardcode references to any backend specific classes, instead only rely on dependency injection, dispatch or polymorphism.

If you want to create a new type of BlElement and implement a custom drawing method, you should first subclass a BlElement (MyElement) and override drawPathOnSpartaCanvas: aCanvas by adding it as an extension method to MyElement in a package named MyProject-Sparta. It is also important to never instantiate Sparta objects by sending new to the corresponding class. Instead, users should let the provided aCanvas (an argument of drawPathOnSpartaCanvas:) play a role of a service provider.

Here is an example of how developers can create a linear gradient paint in order to fill a rectangle on a sparta canvas:

drawPathOnSpartaCanvas: aCanvas
   | gradient |
   super drawPathOnSpartaCanvas: aCanvas.

   gradient := aCanvas paint linearGradient
        begin: 0@0;
        end: 200@100;
        stops: { 0 -> Color red . 1 -> Color blue };
        yourself.

   aCanvas fill
        path: (0@0 extent: 200@100);
        paint: gradient;
        draw.

NOTE: I don't like the name drawPathOnSpartaCanvas: and it will be probably renamed (with deprecation)

syrel commented 7 years ago

In order to keep dependencies clean we also provide a minimalistic installation scripts of Bloc without any rendering/window support:

"Install Bloc and Bloc-Tests packages (no Sparta, no Hosts, no Layouts)"
Metacello new
    baseline: 'Bloc';
    repository: 'github://pharo-graphics/Bloc/src';
    load: #minimal:bloc

The same but with layouts and layout tests:

Metacello new
    baseline: 'Bloc';
    repository: 'github://pharo-graphics/Bloc/src';
    load: #'minimal:bloc+layout'