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