It looks like you're new here. If you want to get involved, click one of these buttons!
Hi,
I know how to add a new toolbar button, as detailed in many other forum questions.
I also know how to draw something (say, a box), select it, and then click Edit menu > Selection > Convert to PCell, then to choose a PCell (say, BasicLibrary's StrokedPolygon) to convert it to PCell.
However I'd like to combine the two above in one fluid process.
Basically, using the examples above, I envisage clicking a custom "Stroked Box" button on the toolbar, then drawing a box with my mouse, then as soon as I have drawn the box it instantly converts it to StrokedPolygon (without me having to select it or press menu items or shortcut keys etc). In other words you click "Stroked Box" button to draw a stroked box. Can this be done?
Thanks!
Comments
Hi David,
well, it probably can be done, but the path is a stony one.
You cannot directly catch mouse events. KLayout implements functionality based on components called "plugins". A component can register itself inside the system and add functionality to menus and the mouse event dispatcher of the application. A big part of KLayout's functionality is implemented as plugins. Plugins can also be provided through Ruby code. As a starting point you can use the documentation of PluginFactory http://klayout.de/doc/code/class_PluginFactory.html.
Only by using that facility you will be able to implement the requested functionality. Implementing a stroked box will be easier than lets say, a stroked polygon. The latter means you'll have to control multiple mouse clicks, handle alignment options and so on.
To make the functionality feel like a built-in function, undo/redo support needs to be added as well, although that is rather simple (the key are so called "transactions" - see http://klayout.de/doc/code/class_LayoutView.html#m_transaction).
So overall that will be a fairly complex project. But it can be done, I'm sure.
Matthias
Thanks Matthias,
I took a look and played with the PluginFactory example - and yes it seems it can be done but may be nontrivial.
Thinking more, an acceptable alternative would be to draw a shape (say, a regular box), then press a user-defined key (like "s") and it converts the just-drawn shape to Stroked Box. I know how to define keyboard shortcuts in Ruby, but am stuck on two things:
1) How to convert the selected shape to PCell, in Ruby.
For this of course I know how to get the selected shape(s) and iterate over them with some action, e.g.
However I can't figure out a way to convert to PCell. I looked in PCellDeclaration but none of those methods do that. I could run
but then I get a dropdown box to choose the PCell that I have to click with my mouse -- instead I want to specify the PCell in code.
2) How to select the just-drawn shape
Say I draw a box. Rather than changing to the select tool and then selecting it, is there a way to get a handle to the just-drawn box in Ruby? I thought maybe in the list of shapes there is a way to find the one we just added. We can assume the box was literally just drawn and the user has not done any other input since.
(Note: I'm actually not interested in Stroked Box - I'm interested in various other more complicated things, but just using this as a simple example.)
Thanks!
Hi David,
I'm somewhat short of time right now and can't give advise immediately. But I'll come back to you. Please ping me in case I forget.
Matthias
Hi David,
Regarding 1.), I just answered a similar request here: http://klayout.de/forum/comments.php?DiscussionID=439&page=1#Comment_1873. In your case, since you have a STROKED_POLYGON PCell, the parameters are
In order to implement the "convert shape to polygon", you'll need to identify the shape you want to convert (that will give you a Shape object). You can then use Shape#polygon to convert it to a polygon which you can assign to the "shape" parameter. After placing a such a PCell instance into the same cell than the original shape you can remove the shape.
Regarding 2.) I'm afraid there is no other solution rather than implementing the mouse actions yourself using the Plugin scheme. Here's a sketch:
I don't have a worked out example that would illustrate that. Maybe I find time to make one, but I can't promise.
Matthias
Thanks Matthias.
Regarding 1.) I tried this, but while it does place a PCell on the layout, it does not appear to use the selected shape as the PCell input. Instead it just places the PCell at the default position, (0,0).
Here is the code. I couldn't use Basic.TEXT because that doesn't allow a TypeShape input, so I changed it to generate a Basic.CIRCLE.
Regarding 2.) Thanks for outlining, and I plan to give this a crack when I've figured out 1.
Thanks!
Ah - of course in the 3rd-to-last line I tell it to create it at (0,0), don't I? Oops.
Well anyway - so I could in this code get the various parameters of the selected shape and from that figure out r, and the x,y location and rotation to place it. However then why do I even need to give it the shape in this line:
in the first place? It seems like in general the calling script must figure out what to set parameters like "radius" and x,y location to --- therefore making the passing of "handle" => obj.shape irrelevant. Is there in fact some need for this?
Thanks!
Hi David,
CIRCLE is not a good example - the "handle" is basically an internal parameter which is not a shape, but a single-point box which represents the handle by which you can graphically edit the radius.
A CIRCLE PCell does not need a shape for input - even though you can convert a shape to a circle. If you want to copy the behavior of the "convert to PCell" function, you'll have to derive the radius from the shape's bounding box (the implementation of Shape to CIRCLE takes the minimum of width and height for the diameter). You could also use PCellDeclaration#parameters_from_shape and PCellDeclaration#transformation_from_shape on the Basic.CIRCLE's PCellDeclarationHelper object to perform this.
A PCell that truly requires a shape for input is ROUNDED_POLYGON for example. For such PCell's the input shape acts as the template and a shape parameter is required to specify that. In that case, I'd suggest to use "obj.shape.polygon" to convert the shape to a polygon and maybe check whether that is possible - the shape could be a text as well. But also for such PCell's the PCellDeclaration#parameters_from_shape and PCellDeclaration#transformation_from_shape works, so maybe that is the more generic approach:
I have not tested that, but that's the way it should work in general, even for CIRCLE. I admit that solution is far more simple than the first suggestion and I should have come up with that earlier.
Matthias