freenode/#clim - IRC Chatlog
Search
9:30:07
ikrabbe
Good morning, today I found a strange behaviour: I wrote a present function for some type. That present function simply prints the object in bold type. Now, in the listener it tries to present the object, but the stream (some drei editor thing) is a string-output-stream, but no extended one, that can be styled in any way, so it breaks. Is that intended?
9:38:06
beach
That sounds strange. I mean, the listener can display any object including graphics. Are you sure you presented it to the right stream.
9:39:11
beach
I can believe that the stream associated with Drei is a string input stream, but I can't see how that would be the stream that the listener uses to display things.
9:48:47
lukego
This is looking like a pleasant day of CLIM'ery for me :-). That's assuming CLIM is the tool for the job I have in mind, which is to use drawing operations like draw-rectangle/with-translation/with-scaling, and output not actual graphics but rather geometry information such as the list of drawn rectangles/polygons with their absolute positions. Am I on the right track? Use output recording and inspect the output records?
9:51:45
beach
I can't think of any. But there are two variables that control drawing and recording. If you set them to NIL and T respectively, you should get the desired effect.
9:52:21
beach
And the stream has an output history which is the root of the tree that contains the output records.
9:52:43
lukego
Is there an easy way to do this such that it doesn't need e.g. X11? (I mean since I don't need to render graphics anywhere but only do the geometry operationS)
9:56:20
ikrabbe
beach, I found that error, in the present method for my type, which changes text-styles. I now have a type switch for the stream that is given to the present function. Possibly I should try to trace it.
9:57:09
beach
Because I just tried in the listener to do (with-text-style (*standard-output* (make-text-style nil :bold nil)) (format t "hello"))
9:57:11
lukego
Thanks. I see also that with-output-recording-options seems to let you say if you want to actually draw or not. I'll dig a bit.
9:57:40
ikrabbe
But with the type switch the record now displays without text-styles in the listener window
9:58:23
beach
The "listener window" is *standard-output* and, my test shows that it can display bold text.
9:59:00
ikrabbe
I will try to choose the text styles from *standard-output* and not from the stream given to the present function, but still this sounds like the start of a bug report.
10:21:05
lukego
Sorry to be dense but is there an easy way, e.g. at the listener, to get an output record representing a draw-rectangle* call? I'm trying stuff but it's erroring e.g. (with-recording-options (t :draw nil :record t) (draw-rectangle* t 0 0 1 1)) errors probably because the latter t should be something else..?
10:28:03
lukego
yeah I'm reading through the docs but I don't get how to create/acquire a suitable medium
10:29:30
lukego
Is the sheet something that I create, or something that already exists that I need to reference, or is that a very context-dependent question? Just now I'm working in the clim listener but ideally I'd be typing expressions into Emacs and seeing results in CLIM instead
10:32:59
lukego
I'm having a hard time because the streams/sheets/etc are being created somewhere deep in CLIM via e.g. run-frame-top-level so I don't really understand e.g. how I could create a throw-away dummy one for these purposes
10:33:05
jackdaniel
lukego: writing to clim stream from the emacs repl is very likely to break - you access stream output history from outside its thread
10:34:08
lukego
so is that idea that I should "live" in the clim listener while experimenting with clim?
10:34:33
jackdaniel
not necessarily, you may execute commands on other application frames (and that is thread safe now)
10:34:48
jackdaniel
another option is to queue an event and handle it on the clim side (also thread safe)
10:35:59
jackdaniel
that said, if you want to implement thread-safe stream operations, I can provide some insight and an idea how that coould be done ;; I'm doing too many things right now to start that task though
10:36:11
lukego
I'm not sure if that's what I want... I don't actually want any graphics at all, I just want to call e.g. draw-rectangle* and get an output record to extract geometry data from. I'm using the listener because that seems like the easiest way to get a medium to draw on
10:37:14
lukego
I did replace t with *standard-output* above ^^ which got rid of the error but didn't actually give me an output record
10:37:22
jackdaniel
alternatives are using the render port, or (even better) the null port; but they are less tested
10:37:33
jackdaniel
if you just want to get the output record, you want to use (with-new-output-record …)
10:38:27
jackdaniel
I have (somewhere) a hack where I've created a *null-stream* that works with with-new-output-record
10:39:19
jackdaniel
ikrabbe: with interactive streams (like drei) it is important to have the text-view specialization that works only with text (for sake of parsing/unparsing results)
10:39:47
jackdaniel
so the easy way out for you would be defining two present methods: one specialized on (view text-view), and second not specialized on it (or specialized on some other view)
10:40:39
jackdaniel
example of interactive stream present use: autocompletion after tab -- if you put there arbitrary output, you could have a command line filled with circles, not really something you could rescan (as in parsing)
10:41:04
jackdaniel
perhaps that would make a nice extension, but I hope that gives you an intuition why it is required to be a string
10:58:16
jackdaniel
(let ((clim:*default-server-path* :null)) (defparameter *stream* (clim:open-window-stream)))
11:00:27
lukego
I really appreciate this. I have a problem where I really don't have a "global" view of CLIM and can get lost on really basic things. Helps immensely to have an example to start from
11:01:22
lukego
This seems to immediately DWIM with with-translation/with-scaling too i.e. the output record contains the final transformed coordinates
11:02:06
jackdaniel
but since it is a null medium, you may have problems if you probe i.e a bounding rectangle of a text output record
11:02:42
jackdaniel
mind, that this is not thread safe either, but since null backend does not generate any events - the "proper" thread doesn't do anything
11:03:05
jackdaniel
so there is no risk of a race condition unless you start multiple threads accessing the stream yourself
11:04:05
jackdaniel
probably a cleaner soultion would be creating an instance of the standard-output-recording-stream and use that as the macro argument, but I haven't tested it
11:12:00
lukego
re: thread-safety, would a simple hack be to just inject a closure into a clim thread to do anything clim-related?
11:12:36
jackdaniel
yes, that's the gist of the solution I have in mind. send a continuation wrapped in an event
11:12:40
lukego
IIRC that's how Java finally resolved their thread safety problems in Swing i.e. just decided that one thread has to own the whole GUI because otherwise it's a nightmare
11:13:52
lukego
*nod* don't let me distract you. hopefully I can help out a bit with stuff if I get my own CLIM application in the air
11:15:21
lukego
CLIM is still a bit magic to me e.g. here https://twitter.com/lukego/status/1363497447532675077 I printed a bunch of debug coordinates with FORMAT and expected them to appear in the SLIME REPL but actually got them in the diagram (which in this case was pretty convenient :-))
11:16:27
jackdaniel
of course you may define your own methods so streams are bound to something else
11:16:56
lukego
I think that I just haven't internalized the idea of graphical streams yet. drawing rectangles with coordinates doesn't feel very stream-like so it's easy to forget about the CLIM model
11:17:54
jackdaniel
think about the clim application pane as a terminal that was designed right (and implemented so-so!)
11:42:06
lukego
btw in the short term should I just roll the dice on thread-safety when calling clim from emacs or e.g. is there some mutex I can grab to make things safe-ish?
12:40:56
lukego
How do you normally lookup CLIM reference documentation e.g. by symbol? There don't seem to be docstrings in mcclim but maybe a clhs-style lookup hack from emacs or something?
12:47:27
jackdaniel
and given I will finish some day the documentation system London, I want to load clim spec to it and have that inside image
12:58:59
lukego
So is (slot-value A-DRAW-RECTANGLE-OUTPUT-RECORD 'clim-internals::coordinates) basically the way to pull apart the info that I want or is there a proper protocol for exatracting things like rectangle bounds? I don't see it in the spec (although maybe I could use bounding boxes as a proxy but that sounds risky)
13:08:27
jackdaniel
there is no protocol to access these. you need to take a look at the draw-rectangle-output-record itself to see what it stores in its slots (of course, that's an implementation detail)
13:11:27
jackdaniel
(but not for polygons that may result from calling medium-draw-rectangle* with non-rectilinear transformation)
13:16:59
lukego
Thanks. I'm digging into transformations now. It would be kind-of neat if I can always draw my rectangles left-to-right even if they are really being drawn e.g. along each side of a rectangle.
13:17:44
lukego
My experiments with rotations so far have given surprising results including giving polygons when I expect rectangles. Hopefully trial and error will get it worked out
13:36:59
lukego
For example suppose that you are drawing the rectangles along the four sides in this picture: https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQN7fLJjMqixkfJkFmYTsndRsyJ85viRtmVNA&usqp=CAU
13:37:50
lukego
if you write the code to draw the top row then you could presumably just run that under four different transformations
14:05:33
jackdaniel
something like that I suppose: http://turtleware.eu/static/paste/062c0ba3-legs.lisp.txt
14:06:08
jackdaniel
mind, that compose-transformations works like the standard transformation composition operator (transformations are applied right-to-left)
14:59:59
lukego
Glad to see that in the example if I capture the output records they are all rectangles. I'd been concerned that some weird stuff might happen due to rotating by floating point angles. Maybe rounding it back to integer pixel coordinates takes care of that.
15:04:48
jackdaniel
huh, there isn't even a kludge, are you sure that said rectangles are not polygon output records?
15:05:31
jackdaniel
(clim:rectilinear-transformation-p (clim:make-rotation-transformation pi)) ; > NIL
15:06:56
lukego
... though that's after I put in a with-output-to-output-record which had the side-effect of not actually rendering that on screen
15:07:32
jackdaniel
that's not what I mean. the instance is expected to always be draw-rectangle-output-record
15:10:31
lukego
yeah I'm thinking from the perspective of wanting to write a function that turns all the CLIM figures into humble (x0 y0 x1 y1) lists at the end
15:11:46
jackdaniel
"pure" clim programmer should always work on streams (which are subclasses sheets)
15:13:02
jackdaniel
most if not all functions that work on medium have trampolines specialized on a sheet
15:13:08
lukego
neat it seems like if I wrap the rectangles in (with-output-as-presentation ...) then the output records are still nice and clear and include juicy metadata that I can put in
15:14:23
jackdaniel
(so if you write tools that help you work with output records, they should work also on presentations)
15:28:40
lukego
So I now find myself writing a generic routine for converting output records into lists, e.g. ((:presentation :foo 'string (:rectangle 0 0 1 1))), and I can't help but wonder if this is a code smell that I've yet to recognize..
15:29:38
lukego
Maybe I should just operate on output records directly instead of converting them? but it seems like most of the interesting accessors are internal to climi so that'd be a bit messy. Or maybe something similar already exists? Or maybe I should be capturing the relevant data during drawing rather than hacking it out of the output records?
15:35:19
jackdaniel
if it is just a flat list of what you put on the screen, you could access them with output-record-children
15:41:02
lukego
I'm writing a program to output a printed circuit board design. I'm trying to do it in two main steps: decide where the components go and then decide how to connect them together.
15:42:12
lukego
For each component I need to pick a position on the board and then draw the "land" for its "footprint" there. That basically means to draw some ink that marks where the copper pads will be for soldering the part onto. So basically I'm drawing the yellowey golden bits of a picture like this: https://file.pcbway.com/websponsor/18/08/29/165932718_Top.png
15:44:00
lukego
Producing an actual drawing like this is important -- I can review it on the screen and I can also send it off to a fabricator to produce the PCB, which is the ultimate goal of the whole endeavor.
15:45:05
lukego
However, I also need to do a separate "routing" step to make all the necessary conncetions between these golden pads. That means basically to draw the dark green lines and make sure they follow all the necessary rules e.g. don't intersect.
15:46:57
lukego
and I'm thinking that the input to the "routing problem" will be basically the set of all those golden pads, including their positions, and the set of connections between them that have to be made. So I need to "reverse engineer" out of the image e.g. the locations of all golden pads that reprsent "Ground" or "1.2V power"and so on
15:48:22
lukego
aaaand the routing will be done on a separate data structure, something called "corner stitching" that I'm knocking off from Ousterhout's ancient 80s/90s CAD stuff. So I need to convert from this very concrete pixel-based repreesntation into a somewhat more abstract cell-based topological one
15:49:04
jackdaniel
I would start with the abstract cell-based topological representation and define presentation methods present on them
15:49:52
jackdaniel
you will still have the output record hierarchy generated from the abstract representation, and you could modify present methods or instances parameters to tweak the board
15:55:10
lukego
That's definitely what I'd do with a regular GUI toolkit. However I'm wondering if a CLIM sheet would make a reasonable data structure for "defining the problem" i.e. placing all of the golden pads that will need to be routed. The downside is that I need a conversion routine to translate that into a topological representation. The upside is that I can use CLIM's convenient drawing functions for defining the pads
15:55:59
lukego
So for example in your example code above ^^^ the repetition of left/right/top/bottom is relying on CLIM transformation functionality that I'd presumably need to write by hand if I "ported" this code to the abstract representation instead