Create array of labels for manifold pins
false
false
true
ruby
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# DESCRIPTION: Creates an array of labels
#
# Run the script with
# klayout -rm array_of_labels.lym ...
# or put the script as "array_of_labels.lym" into the installation path.
#
# This script will install a new entry in the "Macros" menu called "Create array of labels for manifold pins".
# On running it, a dialog will be shown where you can enter the parameters of your label array.
# Each label is given an individual number which can be embedded in the label string.
#
# The parameters are:
# * start position: the point of the first label
# * distance vector: the distance (x,y) between the labels
# * start number: the number of the first label
# * end number: the number of the last label (start number can be larger than end number to get a reverse sequence)
# * format: the label text format (use sprintf notation to embed the number, e.g. "text<%d>")
# * size: the size of the label in µm units
# * orientation: check this box to get vertical labels
# * layer: the layer where to put the labels
#
# Upon "Ok", the label sequence will be generated. Undo/redo is available.
class ArrayOfLabelsDialog < RBA::QDialog
def initialize
mw = RBA::MainWindow::instance
super(mw)
build_dialog
end
def build_dialog
self.windowTitle = "Create Array Of Labels"
gl = RBA::QGridLayout::new(self)
row = 0
label = RBA::QLabel::new
label.text = "Position of first label (x,y)"
gl.addWidget(label, row, 0)
@position = RBA::QLineEdit::new
@position.text = "0,0"
gl.addWidget(@position, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "distance vector between labels (x,y)"
gl.addWidget(label, row, 0)
@distance = RBA::QLineEdit::new
@distance.text = "0,0"
gl.addWidget(@distance, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "Start number"
gl.addWidget(label, row, 0)
@start = RBA::QLineEdit::new
@start.text = "1"
gl.addWidget(@start, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "End number"
gl.addWidget(label, row, 0)
@end = RBA::QLineEdit::new
@end.text = "1"
gl.addWidget(@end, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "Label format (sprintf)"
gl.addWidget(label, row, 0)
@format = RBA::QLineEdit::new
@format.text = "pin<%d>"
gl.addWidget(@format, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "Text size (µm)"
gl.addWidget(label, row, 0)
@text_size = RBA::QLineEdit::new
@text_size.text = "1.0"
gl.addWidget(@text_size, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "Text orientation"
gl.addWidget(label, row, 0)
@text_rotated = RBA::QCheckBox::new
@text_rotated.text = "Rotated 90 degree"
gl.addWidget(@text_rotated, row, 1)
row += 1
label = RBA::QLabel::new
label.text = "Layer (layer/datatype)"
gl.addWidget(label, row, 0)
@layer = RBA::QLineEdit::new
@layer.text = "1/0"
gl.addWidget(@layer, row, 1)
row += 1
gl.setRowStretch(row, 1)
row += 1
hbl = RBA::QHBoxLayout::new
gl.addLayout(hbl, row, 0, 1, 2)
hbl.addStretch(1)
ok = RBA::QPushButton::new
ok.text = "Ok"
ok.clicked do
begin
self.check
self.accept
rescue => ex
RBA::QMessageBox::critical(self, "Error", ex.to_s)
end
end
hbl.addWidget(ok)
cancel = RBA::QPushButton::new
cancel.text = "Cancel"
cancel.clicked do
self.reject
end
hbl.addWidget(cancel)
end
def check
ly = RBA::CellView::active.layout
lspec = RBA::LayerInfo::from_string(@layer.text)
lindex = ly.find_layer(lspec)
if ! lindex
raise("No layer present with the given specification (#{@layer.text})")
end
@lindex = lindex
if !(@position.text.gsub(/\s/, "") =~ /^([\d.eE+-]+),([\d.eE+-]+)$/)
raise("Position is not a pair of coordinates (#{@position.text})")
end
@start_point = RBA::DPoint::new($1.to_f, $2.to_f)
if !(@distance.text.gsub(/\s/, "") =~ /^([\d.eE+-]+),([\d.eE+-]+)$/)
raise("Distance vector is not a pair of coordinates (#{@distance.text})")
end
@distance_vector = RBA::DVector::new($1.to_f, $2.to_f)
if !(@start.text.gsub(/\s/, "") =~ /^([\d-]+)$/)
raise("Start number is not an integer (#{@start.text})")
end
@start_number = $1.to_i
if !(@end.text.gsub(/\s/, "") =~ /^([\d-]+)$/)
raise("End number is not an integer (#{@end.text})")
end
@end_number = $1.to_i
end
def start_point
@start_point
end
def distance_vector
@distance_vector
end
def start_number
@start_number
end
def end_number
@end_number
end
def lindex
@lindex
end
def format
@format.text
end
def text_size
@text_size.text.to_f
end
def text_orientation
@text_rotated.isChecked ? 1 : 0
end
end
view = RBA::LayoutView::current
cv = RBA::CellView::active
if ! view || !cv
RBA::QMessageBox::critical(RBA::MainWindow::instance, "Error", "No layout opened")
else
# for debugging:
# $array_of_labels_dialog && !$array_of_labels_dialog._destroyed? && $array_of_labels_dialog._destroy
# $array_of_labels_dialog = ArrayOfLabelsDialog::new
# for production:
$array_of_labels_dialog ||= ArrayOfLabelsDialog::new
dia = $array_of_labels_dialog
if dia.exec != 0
begin
view.transaction("Create array of labels")
numbers = []
if dia.start_number > dia.end_number
(dia.end_number..dia.start_number).reverse_each { |i| numbers << i }
else
(dia.start_number..dia.end_number).each { |i| numbers << i }
end
pos = dia.start_point
numbers.each do |n|
str = dia.format % n
text_trans = RBA::DTrans::new(dia.text_orientation, false, pos.x, pos.y)
text = RBA::DText::new(str, text_trans)
text.size = dia.text_size
cv.cell.shapes(dia.lindex).insert(text)
pos += dia.distance_vector
end
ensure
view.commit
end
end
end