Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Edward K. Ream
In the Contributing to Flexx 
 page Almar says, 
"it’s very useful to hear what you like and what you struggle with. This 
post summarizes both topics.

*= Part 1: What I like about flexx*

Flexx makes bi-directional, asynchronous communication between Python and 
the browser as simple as it could possibly be. Specifically: 

*1. Simple code suffices*. The top-level flexx code to draw Leo's main 
window could be as simple as:

class LeoMainWindow(flx.Widget):

def init(self, body, outline):
with flx.VBox():
with flx.HBox(flex=1):
LeoTree(outline, flex=1)
LeoLog(flex=1)
LeoBody(body, flex=1)
LeoMiniBuffer()
LeoStatusLine()

As discussed later, we might want to add flexx properties to this code to 
make the individual components more easily accessible to other classes.

*Important*: As shown above, init methods can take extra *non*-keyword args 
(body and outline) which can then be passed to "inner" flx.Widgets.  In 
turn flexx (magically) passes those args to the init methods of the inner 
Widgets.  Nothing special needs to be done to make this happen! This 
greatly simplifies communication between components. There is typically no 
need to define __init__ methods.


*2. Pscript rocks*

The pscript documentation 

 
says: "[Unlike] Skulpt or PyJS...PScript takes a more modest approach; it 
is a tool that allows one to write JavaScript with a Python syntax. PScript 
is just JavaScript."

This limited goal shows superb engineering judgment. Its simplicity makes a 
huge difference.  The pscript compiler is straightforward!

One need not worry greatly about the differences between pscript and 
python, for several reasons:

- Error reporting is excellent. The one time I used a Python construct (a 
generator inside a list) that pscript does not support at present, pscript 
gave me a clear error message.

- Typical flexx programs will be as simple as the example shown above.  
Pscript undoubtedly suffices to handle such code.  Imo, that's all that 
matter. 

3. *The documentation and support are excellent*

Flexx's docs are easy to read and comprehensive.  By almost any measure 
they are superior to Leo's. The examples, demos and how-to's are especially 
valuable.

I have asked Almar two questions on flexx's issue tracker 
. Each time 
I received a prompt, helpful, and courteous reply.

*= Part 2: What I struggled with*

I have just said that flexx's docs are excellent.  Nevertheless, it has 
taken four days of intense work for me to attain limited proficiency.  This 
is completely expected.  I learn by doing, not by reading.

After yesterday's work I am much more confident that I can use flexx as 
Almar himself might use it. Now is the time to write this section, while 
the difficulties and confusions are still fresh in my mind.

*What gets compiled to pscript?*

This has been a big confusion.  *Just now* I see that Almar answered this 
question completely here 
.  So 
the answer is: PyComponents are *not* JS. That helps a lot.

For example, LeoApp is a flx.PyComponent, so its open_bridge, find_body and 
get_outline_list methods do *not* get compiled to JS.  If they did, they 
could not possibly work, because these methods use Leo's Commander objects 
(c), and there is no way that JS is ever going to be able to deal with this 
class.  Indeed, a few days ago I was getting JS errors to that effect.

In this reply 
, Almar 
said: "this pinpoints Flexx' weak spot; it makes writing Js classes so 
familiar that confusion arises :/ I'd recommend to separate the two as good 
as you can. Be explicit in comments / docstrings. Probably don't mix the 
two in a single module."

Well, this is a pretty small weak spot :-) Devs obviously must distinguish 
carefully between the Python and JS sides!  That's a big part of what 
coming up to speed with flexx entails.

At present leoflexx.py contains two top-level organizer nodes called:

- Py side: flx.PyComponents
- Js side: flx.Widgets

Imo, these "comments" suffice.  It would not be Leonine to put those two 
sub-outlines in separate modules.

*When does transpiling happen?*

Traces reveal that pscript issues errors as the server starts up.  Again, 
this could be called a Doh! moment.  Where else is the transpiling going to 
happen?  Still was helpful to get that leoflexx.py is *just* a python 
program as far as python itself is concerned.  The magic happens later.

*How to communicate between components?*

Given the example above, you would think this would be no big deal, but it 
was a very big deal indeed. The example is the result of many hours of

Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread rengel
Thanks for sharing!
How did you run LeoMainWindow, in the browser - app.launch('browser') - or 
as a desktop app - app.launch('app')? If you tried the second variant, did 
you set some window parameters using a CSS stylesheet? If so, how? Right 
now, I couldn't figure out how to set the parameters of the main window. I 
tried:

from flexx import flx

class MainWindow(flx.Widget):

 CSS = """
 .flx-VBox {width: 1200px; height: 800px; background: red;}
 """

 def init(self):

 with flx.VBox():
 self.workspace = flx.Widget(style='width: 1200px; height: 800px; 
background:#cc;', flex=1)


app = flx.App(MainWindow)
app.export('main.html', link=0) # Export to a single file
# app.launch('browser') # show it now in a browser
app.launch('app') # show it as a desktop app
flx.run() # enter the main loop

Both the CSS and the inline style honor the color settings, but not the 
with and height settings.

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Edward K. Ream
On Thursday, November 8, 2018 at 8:35:30 AM UTC-6, rengel wrote:

Thanks for sharing!
>

You're welcome.

How did you run LeoMainWindow, in the browser - app.launch('browser') - or 
> as a desktop app - app.launch('app')? 
>

>From a console I ran a .bat file containing just:

python leo\plugins\leoflexx.py --flexx-webruntime=
browser

The top-level of leoflexx.py is now just:

import leo.core.leoBridge as leoBridge
from flexx import flx
@others
if __name__ == '__main__':
flx.launch(LeoApp, runtime='firefox-browser')
print('After flx.launch')
flx.run()

On my machine this opens mozilla.

did you set some window parameters using a CSS stylesheet? 
>

All the .css is in leoflexx.py.  In particular, the body page uses ace, 
whose startup code contains:

self.ace.setTheme("ace/theme/solarized_dark")

I couldn't figure out how to set the parameters of the main window.
>
[snip]

> Both the CSS and the inline style honor the color settings, but not the 
> with and height settings.
>

My guess is that the VBox() and HBox() layouts override the width and 
height settings.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Edward K. Ream
On Thursday, November 8, 2018 at 8:35:30 AM UTC-6, rengel wrote:

did you set some window parameters using a CSS stylesheet?
>

I just talked to my brother Speed, and he said that leoflexx.py is causing 
files to be downloaded.  Indeed it is. I'm not sure this is related to your 
question, but here goes.

In the LeoBody node, just before the definition of class LeoBody, the 
following appears:

base_url = 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/'
flx.assets.associate_asset(__name__, base_url + 'ace.js')
flx.assets.associate_asset(__name__, base_url + 'mode-python.js')
flx.assets.associate_asset(__name__, base_url + 'theme-solarized_dark.js')

This might be a concern for some people.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Edward K. Ream
On Thursday, November 8, 2018 at 7:04:05 AM UTC-6, Edward K. Ream wrote:

*How to communicate between components?*
>

[big snip]

Happily, flexx properties provide everything needed.  Apparently, 
> properties must be used to communicate even between different flx.Widgets.  
> That is, the ivars of one widget are not accessible to other flx.Widgets.  
> So the example code above might better be rewritten this way:
>
> class LeoMainWindow(flx.Widget):
> 
> """
> Leo's main window, that is, root.main_window.
> 
> Each property x below is accessible as root.main_window.x.
> """
> 
> body = flx.AnyProp(settable=True)
> log = flx.AnyProp(settable=True)
> minibuffer = flx.AnyProp(settable=True)
> status_line = flx.AnyProp(settable=True)
> tree = flx.AnyProp(settable=True)
>
> def init(self, body, outline):
> with flx.VBox():
> with flx.HBox(flex=1):
> tree = LeoTree(outline, flex=1)
> log = LeoLog(flex=1)
> body = LeoBody(body, flex=1)
> minibuffer = LeoMiniBuffer()
> status_line = LeoStatusLine()
> self._mutate_body(body)
> self._mutate_log(log)
> self._mutate_minibuffer(minibuffer)
> self._mutate_status_line(status_line)
> self._mutate_tree(tree)
>

I buried the lede big time here.  I wanted to emphasize that *all* 
flx.Widgets have a root ivar 
,
 
which is the LeoApp instance.  So it's easy to add to the log widget!  For 
example, here is the event handler in the LeoTree class:

@flx.reaction(
'tree.children**.checked',
'tree.children**.selected',
'tree.children**.collapsed',
)
def on_event(self, *events):

log = self.root.main_window.log
for ev in events:
id_ = ev.source.title or ev.source.text
kind = '' if ev.new_value else 'un-'
s = kind + ev.type
log.put('%s: %s' % (lpad(s, 15), id_))

Recall that pscript does not support features such as "10%s" which is why 
the code above does padding by hand using the global lpad function. 
Finally, here is log.put:

def put(self, s):
self.ace.setValue(self.ace.getValue() + '\n' + s)

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Edward K. Ream
On Thursday, November 8, 2018 at 7:04:05 AM UTC-6, Edward K. Ream wrote:

I forgot to mention that instantiating a flx.Widget or flx.PyComponent does 
*not* cause the init methods to be called immediately.  That happens (much) 
later.  In particular,  calls to self._mutate_whatever will set properties 
at some (much) later time.

This does not cause difficulties, provided that one doesn't expect instant 
action.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Terry Brown
On Thu, 8 Nov 2018 08:47:39 -0800 (PST)
"Edward K. Ream"  wrote:

> On Thursday, November 8, 2018 at 7:04:05 AM UTC-6, Edward K. Ream
> wrote:
> 
> *How to communicate between components?*

I'd evaluate the emit / react ( / action) framework too - avoids having
to have everything know about everything else.

Cheers -Terry

> [big snip]
> 
> Happily, flexx properties provide everything needed.  Apparently, 
> > properties must be used to communicate even between different
> > flx.Widgets. That is, the ivars of one widget are not accessible to
> > other flx.Widgets. So the example code above might better be
> > rewritten this way:
> >
> > class LeoMainWindow(flx.Widget):
> > 
> > """
> > Leo's main window, that is, root.main_window.
> > 
> > Each property x below is accessible as root.main_window.x.
> > """
> > 
> > body = flx.AnyProp(settable=True)
> > log = flx.AnyProp(settable=True)
> > minibuffer = flx.AnyProp(settable=True)
> > status_line = flx.AnyProp(settable=True)
> > tree = flx.AnyProp(settable=True)
> >
> > def init(self, body, outline):
> > with flx.VBox():
> > with flx.HBox(flex=1):
> > tree = LeoTree(outline, flex=1)
> > log = LeoLog(flex=1)
> > body = LeoBody(body, flex=1)
> > minibuffer = LeoMiniBuffer()
> > status_line = LeoStatusLine()
> > self._mutate_body(body)
> > self._mutate_log(log)
> > self._mutate_minibuffer(minibuffer)
> > self._mutate_status_line(status_line)
> > self._mutate_tree(tree)
> >
> 
> I buried the lede big time here.  I wanted to emphasize that *all* 
> flx.Widgets have a root ivar 
> ,
>  
> which is the LeoApp instance.  So it's easy to add to the log
> widget!  For example, here is the event handler in the LeoTree class:
> 
> @flx.reaction(
> 'tree.children**.checked',
> 'tree.children**.selected',
> 'tree.children**.collapsed',
> )
> def on_event(self, *events):
> 
> log = self.root.main_window.log
> for ev in events:
> id_ = ev.source.title or ev.source.text
> kind = '' if ev.new_value else 'un-'
> s = kind + ev.type
> log.put('%s: %s' % (lpad(s, 15), id_))
> 
> Recall that pscript does not support features such as "10%s" which is
> why the code above does padding by hand using the global lpad
> function. Finally, here is log.put:
> 
> def put(self, s):
> self.ace.setValue(self.ace.getValue() + '\n' + s)
> 
> Edward
> 

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread rengel
Both the CSS and the inline style honor the color settings, but not the 
with and height settings.

>
> My guess is that the VBox() and HBox() layouts override the width and 
> height settings.
>
> Thank you for all the detailed answers!
I might have found the answer in one of the examples (in case you're 
interested:
https://flexx.readthedocs.io/en/stable/examples/hv_layout_src.html#hv-layout-py)
It contains several widgets with different sizes set. I'll try them out 
tomorrow and will keep you posted.

Reinhard

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-08 Thread Edward K. Ream
On Thu, Nov 8, 2018 at 11:42 AM rengel  wrote:

Thank you for all the detailed answers!
> I might have found the answer in one of the examples (in case you're
> interested:
>
> https://flexx.readthedocs.io/en/stable/examples/hv_layout_src.html#hv-layout-py
> )
> It contains several widgets with different sizes set. I'll try them out
> tomorrow and will keep you posted.
>

Thanks.  It's good to see people getting excited about this.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-09 Thread Almar Klein
Thanks for sharing this Edward! Thank you for your kind words about Flexx 
and PScript. And thanks for taking the time to write down your struggles. 
I'll try to boil it down to some points of action in Flexx/#516.


> Almar, please correct me if I am wrong about [using props like this].

Yes, you need to make properties for things that you want to make available 
from both Python and JS. Regular attributes work, but *only* withing Python 
or JS (depending on whether its a PyComponent or JsComponent).

BTW, you can use flx.ComponentProp() for components. A pattern which I like 
is to define actions on a "central" PyComponent (I refer to this as the 
`store` in the docs, but it can be the root app) so that you have a 
single"entry point" for JS calling out to Python. You can do something 
similar for the JS side. But I don't know if this works well for your 
use-case.


> Apparently, properties must be used to communicate even between different 
flx.Widgets. 

Or actions or events. Properties should be used to represent state. Actions 
are to "make stuff happen". Sometimes this can be a change in state. E.g by 
using the standard property setters. But actions don't have to mutate 
properties. Beware that actions are asynchronous; they don't apply the 
moment you call them (unless called from an action). This means that an 
action like x.delete_line() is better than taking all lines, deleting one, 
and setting the lines property again. Custom events are probably rare, but 
can be used for things that "happen" (e.g. some form of user input).


> Both the CSS and the inline style honor the color settings, but not the 
width and height settings.

This was answered already, but just to confirm: Flexx indeed overwrites 
these values. Any layout must be done using Flexx' layout classes. Also see 
e.g. the Widget.minsize and Widget.maxsize properties.


> leoflexx.py is causing files to be downloaded. 

You can also use local assets (put the ace.js etc. in the repo and include 
that). Someone recently made an howto for that: 
https://flexx.readthedocs.io/en/stable/examples/local_assets_src.html#local-assets-py


-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-09 Thread Edward K. Ream
On Thursday, November 8, 2018 at 11:17:31 AM UTC-6, Terry Brown wrote:

I'd evaluate the emit / react ( / action) framework too - avoids having 
> to have everything know about everything else. 
>

Thanks for this.  Today's work will be about communicating between the 
Python code in LeoApp and the JS code in LeoTree, so that the JS code can 
update the body pane when switching nodes. I expect no major problems, but 
we shall see.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Learning flexx, part 2, and LeoWapp status

2018-11-09 Thread Edward K. Ream
On Friday, November 9, 2018 at 5:18:42 AM UTC-6, Almar Klein wrote:

BTW, you can use flx.ComponentProp() for components. 
>

Thanks.  I didn't know that ComponentProps existed.

A pattern which I like is to define actions on a "central" PyComponent (I 
> refer to this as the `store` in the docs, but it can be the root app) so 
> that you have a single"entry point" for JS calling out to Python. You can 
> do something similar for the JS side.
>

I'll play with this.  It's probably just what is needed.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.