Open ccoupe opened 7 years ago
Reopened and change the title and the contents of the head post.
What is wrong with extending TextBlock?
Re-read the original request/thread #294 from the top where @dredknight knows he can get the width from an on screen textblock. There is no need to extend textblock with a new method that does what the existing methods do. He wants to know the size in pixels before it's drawn or placed into Shoes GUI processing. A reasonable request. Yes, it breaks compatibility with Shoes 4 but that was done long ago.
This can also be used by folks that want to size their layout based on strings they have little control over width without knowing it's on screen width (reading a sqllite db perhaps).
Here's bugs/bug298.rb
Shoes.app do
stack do
para "measure_text test"
str = "this is my String"
flow do
@p = para str
para "it's #{@p.width} wide"
end
#w,h = measure_text str
#para "it might be #{w} wide"
start do
para "or is it #{@p.width}"
end
end
end
This always been an issue in Shoes where objects that should be available after their creation are only available at runtime. TextBlock#measure would do just fine if Shoes would make objects readily available (as it should). In fact, any width and height from any Shoes element would do justice to its rendering.
There are many things we all would like to have available after the creation of Shoes elements without the need for a hack such as start
(or timer(0) {}
for that matter). The current expectation from Shoes programmers is that they use start
to get access to such kind of information because it's only available at runtime. No need to pollute Shoes DSL to patch bit by bit instead of fixing some other major issue.
By the way, wouldn't measure_text
come short if the string has some fancy text formatting such as strong ?
if Shoes would make objects readily available (as it should)
This can't be done with the with the existing code base and dsl. I don't think cocoa can do it and it may not be possible to turn on synchronous drawing in gtk3 either. It would be a big mess/rewrite that I have no desire to do. I know every newbie assumes a top down lexical order of execution and its a big "Ah Ha!" moment when they figure it out.
By the way, wouldn't measure_text come short if the string has some fancy text formatting such as strong ?
Good catch! Simplifies some things. We can't use Styles here, just a font (but those can be bold). Further isolates this from 'normal' Shoes and another opportunity in the manual to explain start() because we know most newbies don't know about start().
This can't be done with the with the existing code base and dsl. I don't think cocoa can do it and it may not be possible to turn on synchronous drawing in gtk3 either. It would be a big mess/rewrite that I have no desire to do.
It shouldn't be as challenging as it sounds but nothing obvious either. My understanding by now is that fixing this issue wouldn't affect backward compatibility. The Shoes code and user code are loaded before Shoes.app is started. No need to worry about rewriting at the moment, we most certainly need a better understanding first.
Good catch! Simplifies some things. We can't use Styles here, just a font (but those can be bold). Further isolates this from 'normal' Shoes and another opportunity in the manual to explain start() because we know most newbies don't know about start().
Well, what is the point of measure_text
without Shoes styling?
Emphasis in the manual on start
would be really good.
I have some data. Tiny rewrite on the bugs298.rb script and the proposed codes doesn't handle font_setting yet but you can clearly see the "Shoes add" vs pure pangocairo.
128,21 for measure_text vs 120,35 from start(). I consider that probably a failure so before I do a lot of work getting the font setting code (not C fun), I'd want to know what @dredknight thinks of that mismatch. I suspect the huge difference in height is because of Shoes layout of may be because stack margins are are being 'added'
we most certainly need a better understanding first.
There is no way in hell to pre-determine sizes of all stack, flows, text, or widgets until they are all drawn using some arcane and fundamental C code (shoes_place_decide and friends). Then everything changes by appending or remove something in a containing slot. What you appear to want is a static layout option for Shoes which is what Gtk really wants so Shoes is pushing the GTK edges. Cocoa really doesn't want to do static layouts (violates all kinds of Apple good-practices) and has a slot mechanism of its own that more closely matches Shoes slots - compare the size of Shoes gtk.c and cocoa.m. OSX doesn't report the screen position until everything is drawn. Apple also changes it's idea of good-practices frequently.
Yes one can set w,h,x,y, margins.... by pixels In Shoes but you'd have to do it for every thing in your Shoes app in which case you already know where to put things and how big they can become.
Looking deeper into ruby.c and how it parses font settings for textblocks and the backtrace suggests it's ugliness is called at redraw event time, it's even more unlikely this brain cramp will be implemented.
#0 shoes_app_style_for (block=0x115f770, app=0xec58d0, klass=11049920, oattr=8,
start_index=0, end_index=17) at shoes/ruby.c:2487
#1 0x0000000000442eed in shoes_textblock_make_pango (app=0xec58d0,
klass=11049920, block=0x115f770) at shoes/ruby.c:2742
#2 0x00000000004430f4 in shoes_textblock_on_layout (app=0xec58d0,
klass=11049920, block=0x115f770) at shoes/ruby.c:2768
#3 0x0000000000443fec in shoes_textblock_draw (self=17811280, c=17811600,
actual=0) at shoes/ruby.c:2865
#4 0x00007ffff7adbb6f in vm_call0_cfunc_with_frame (argv=0x7fffffffa190,
I removed git knowledge of this brain cramp. I've got a local copy that's not in git - just in case . Consider this a dead issue. not closed yet.
lol I have been away for 3 days and this happened! Thank you for the effort :)! Can I help with something?
There is no way in hell to pre-determine sizes of all stack, flows, text, or widgets until they are all drawn using some arcane and fundamental C code (shoes_place_decide and friends). Then everything changes by appending or remove something in a containing slot. What you appear to want is a static layout option for Shoes which is what Gtk really wants so Shoes is pushing the GTK edges.
You got it all backwards. All I am saying is that Shoes elements should be available once they are fully created in the code. It means a given element has to return, thus is drawn, before resuming to the next line of code.
Let's say a stack has one para and two buttons. The stack is created (but not returned yet), it iterates and adds elements (one para, two buttons); first the para is created, drawn and return (para size should be already known here), then each button is created, drawn and return one-by-one (their sizes should be available at the moment they return); finally, the stack is completed and also returns (the whole stack size should be known and available after the return).
Shoes only relinquishes control to Ruby after its fully completed instead of yielding.
No, I didn't get it backwards. I may not have communicated it in a way you understand. You are describing synchronous drawing. I think the first release of MacOS back in 1984 did that but they soon changed to asynchronous/queued drawing and event queues for performance reasons. To do what your describe using modern gui libraries would require a very delicate set of locking mechanisms between Shoes and gtk and Shoes & osx. Not once source of fail, but two. It's a bad idea to work against your OS (two of them) even paid pro's wouldn't do it.
Shoes only relinquishes control to Ruby after its fully completed instead of yielding.
No, Ruby is used to run the block and create of the para and buttons in the stack. It's not all C.
It's even worse, in Shoes there is two drawing route : Cairo and Native (OS gtk/cocoa), roughly Cairo is in charge of Shapes, Text ... and Native for widgets, provide the surface on which Cairo draws and is the conductor. You can actually go synchronous with Cairo, i've done it, briefly, if you remember, until you probably hit performance wall and probably a bunch of problems i'm not aware of... But, at least, Gtk (guessing cocoa is the same) is a no go : drawings happens in 2 times, first pass (Request) is for acquiring knowledge of placements (who, where, how much) which therefore needs to go through all the elements : containers ask children where they want to be placed and how much space they request - it means container must know all elements before drawing them, then comes the second pass which can give precise placements to all elements : containers are able to calculate now, placements for children -- those placements have not to be the same as the one requested !! containers decides in light of the preceding pass ! (plus gtk3 have some default automatic placement routines, which gets on Shoes way, we had to subclass gtk Widgets to re-acquire control on them ...) All this is taking time and resources and could/would block the ui Thread, so it's done asynchronously. In C, why_ recreated from scratch, all the processing you find in regular gui to manage all this, don't even think to change at a deep level the way it works without beyond rock solid nerves (there's a realm of Macros waiting for your zen enjoyment there, amount of tests equals Nada ! ...) or taking the time to rewrite entirely the whole thing (Shoes4 i guess).
I suspect that the FPS gui paradigm mainly found in games realm, SFML or the like, which looks synchronous (just a loop processing events, eventually queued ?), forces you to go bare metal to have acceptable Fps, so probably no Ruby (just a wild guess here)
Start method is not a hack, it's the way to manage this at the apparently synchronous gui level, it wasn't totally completed (still room for improvement...) so we had to resort to timer(0) for a while, which is a hack !
Another way to think about the issue is from the perspective of callback which gkt3 uses as does cocoa (in an obj-C way) which is what widgets . There is no callback for drawing text because text, shapes,art are not widgets. It's very fundamental Shoes design choice of _why and changing that ripples everywhere.
This experiment of measure_text was relatively easy to try but it's not going to work for what @dredknight wanted (or anybody else).
as discussed in #294 Measure the text height and width of string (and styles) without triggering GUI bye adding a para (and hiding it until later). It needs to be a canvas method which I'm going to call 'measure_text' (until I get a better name). Behind the scene it just calsl some pangocairo stuff and does not trigger redraws, add to slots.