<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">

<doc>

  <title>Introduction</title>
  <keyword name="Programming"/>
  <keyword name="RBA"/>
  <keyword name="Ruby scripts"/>
  <keyword name="Python"/>
  <keyword name="pya"/>
  <keyword name="Python scripts"/>

  <p>
  This chapter is about programming extensions for KLayout using the integrated Ruby API (RBA) or Python API (pya). 
  </p>

  <p>
  To use RBA scripts, KLayout must be compiled with the Ruby interpreter. Check under "Help/About" whether 
  support is available. If there is, the "Build options" will include a "Ruby" or "Python" interpreter or both.
  RBA scripts require a Ruby interpreter. To use pya scripts, Python support must be included.
  </p>

  <p>
  KLayout comes with the Qt library included into the Ruby or Python API. This means, KLayout scripts
  can access the full Qt API if Qt binding is available. Check whether "Qt bindings for scripts" is included
  in the build options on the "Help/About" page.
  </p>

  <p>
  Basically there are scripts and macros:
  </p>

  <ul>
    <li>
      <b>Scripts</b> are simple text files which are prepared externally and KLayout acts as an interpreter for these scripts.
      A special case of scripts is included code, while is loaded into other scripts or macros using "require" on Ruby
      or "import" on Python. Scripts have been the only way to code Ruby functionality in version 0.21 and earlier.
    </li>
    <li>
      <b>Macros</b> are special XML files which contain Ruby code plus some additional information required to  
      link them into the system, i.e. automatically execute them on startup or provide menu entries for them.
      They can load normal ".rb" or ".py" files to implement libraries of classes in the usual way. Macros are managed and developed conveniently
      in the integrated macro development environment along with the supporting files. This method is the preferred way of creating application
      extensions and is described in this chapter.
    </li>
  </ul>

  <p>
  Before you start, please make yourself familiar with the macro development integrated environment (<link href="/about/macro_editor.xml"/>).
  This documentation also assumes that you familiar with the Ruby programming language. There are numerous 
  books and tutorials about Ruby. The most famous one is the "pickaxe book" (Programming Ruby - The Pragmatic Programmers Guide) by Dave Thomas.
  If you are familiar with Ruby there is a technical article about the way Ruby and KLayout's core are
  integrated (<link href="/programming/ruby_binding.xml"/>). There are special articles about the integrated Qt binding
  (<link href="/programming/qt_binding.xml"/>) and PCell programming (<link href="/programming/ruby_pcells.xml"/>). If you want to 
  use Python, please read the python implementation article (<link href="/programming/python.xml"/>) for details about how to
  translate Ruby samples into Python and specific details of the Python integration.
  </p>

  <p>
  An introduction into the basic concepts of the KLayout API are given in the article about the 
  application API (<link href="/programming/application_api.xml"/>) and about the database API (<link href="/programming/database_api.xml"/>).
  </p>

  <h2>A First Sample</h2>
  
  <p>
  The first sample is already a complete macro which counts all selected paths, boxes, polygons or text objects.
  It demonstrates how to set up a macro, how to deal with the selection and how to access the layout database.
  </p>

  <p>
  Here is the code:
  </p>

  <pre>module MyMacro

  include RBA

  app = Application.instance
  mw = app.main_window

  lv = mw.current_view
  if lv == nil
    raise "Shape Statistics: No view selected"
  end

  paths = 0
  polygons = 0
  boxes = 0
  texts = 0

  lv.each_object_selected do |sel|

    shape = sel.shape

    if shape.is_path?
      paths += 1
    elsif shape.is_box?
      boxes += 1
    elsif shape.is_polygon?
      polygons += 1
    elsif shape.is_text?
      texts += 1
    end

  end

  s = "Paths: #{paths}\n"
  s += "Polygons: #{polygons}\n"
  s += "Boxes: #{boxes}\n"
  s += "Texts: #{texts}\n"

  MessageBox::info("Shape Statistics", s, MessageBox::Ok)

end</pre>

  <p>
  To run the macro, create a new macro in the macro development IDE: choose "Macros/Macro Development". Create a new macro 
  using the "+" button. Rename the macro to a suitable name. Copy the code above into the text. Load a layout, select some
  objects and in the macro development IDE press F5. A message box will appear the tells us how may boxes, polygons etc. 
  we have selected.
  </p>
  
  <p>
  If we look at the code, the first observation is that we put the whole script into our own namespace (we can use any name which is not used
  otherwise). The advantage of that approach is that we can import the "RBA" namespace which makes life somewhat easier.
  The RBA namespace contains all KLayout classes and constants.
  If we would import the RBA namespace into the main namespace we would do that for all other scripts in KLayout since 
  the main namespace is a common resource for all scripts.
  </p>

  <p>
  The first thing we do inside the macro is to access the layout view:
  </p>

  <pre>  app = Application.instance
  mw = app.main_window

  lv = mw.current_view
  if lv == nil
    raise "Shape Statistics: No view selected"
  end</pre>

  <p>
  The Application class (<class_doc href="Application"/>) is a representative for the KLayout application. Since there is only one application, it is a singleton.
  We can obtain the singleton instance with the class method ("static" in the language of C++) "instance". It delivers a
  reference to the only Application object which is the main entrance to all internals of KLayout.
  </p>

  <p>
  The next object which is important is the MainWindow object (<class_doc href="MainWindow"/>). Currently there is only
  one MainWindow object which can be obtained with the "main_window" method of the Application object. The MainWindow 
  object represents the application's window and manages the top level visual objects of the application.
  The main visual components of the main window are the menus, the tool panels (cell tree, layer list, tool box, navigator ...) 
  and the layout views. 
  </p>

  <p>
  The layout view is the representation of a layout tab (<class_doc href="LayoutView"/>). That is basically the window to 
  the layouts loaded into that tab. 
  All related information such as the display settings, the zoom area, the layer properties and the information about the 
  cell shown, the hierarchy levels and further settings go here. 
  </p>

  <p>
  A main window can display multiple tabs. Hence there are multiple LayoutView objects available. The currently selected
  tab can be addressed with the "current_view" method. This method delivers the LayoutView object associated with that tab.
  If no layout is loaded, that method returns nil (the Ruby  for "nothing")
  </p>

  <p>
  Actually the preparation step can be simplified without needing the Application and MainWindow object. For demonstration
  purposes it was included however. Here is the short version:
  </p>

  <pre>  lv = LayoutView.current || raise "Shape Statistics: No view selected"</pre>

  <p>
  The actual layouts loaded are entities separated from the views. Technically, there is a many-to-many relationship between layout views
  and layout objects. A layout view may display multiple layouts and one layout may be displayed in multiple layout views.
  In addition, a layout view can address different cells from a layout. A layout view has a current cell and a path 
  that leads to that cell. The path consists of a specific and unspecific part. The unspecific part of the path tells 
  where the cell we show as the current cell is located in the cell tree. The unspecific part is a tribute to the fact that
  a cell can appear in different branches of the cell tree (i.e. as child of cell A and cell B). The specific part of the
  path addresses a specific instance of within some cell (the "context cell") above in the hierarchy. A specific path is created when 
  we descend down in the hierarchy along a certain instantiation path.
  </p>
  
  <p>
  Layout, current cell, context cell, specific and unspecific 
  path are combined into the CellView object (<class_doc href="CellView"/>). A layout view can have multiple cell views
  corresponding to the different layouts that can be loaded into a panel. The cell views do not necessarily have to point
  to different layouts.
  </p>

  <p>
  For our sample we don't need the CellView objects, because we get all information directly from the view. But the 
  concept of that object is important to understand the API documentation.
  Here we ask the layout view for all selected objects and collect the object counts:
  </p>

  <pre>  lv.each_object_selected do |sel|

    shape = sel.shape

    if shape.is_path?
      paths += 1
    elsif shape.is_box?
      boxes += 1
    elsif shape.is_polygon?
      polygons += 1
    elsif shape.is_text?
      texts += 1
    end

  end</pre>

  <p>
  "each_object_selected" is a method of the LayoutView object. More precisely it's an iterator which calls the
  given block for each selected object. Since the layout view can show multiple layouts, the selected objects may
  originate from different layouts. In addition, the object may be selected in a child cell of the current cell.
  Hence, the selection is described by a cell view index (indicating which layout it resided in), an instantiation path (a sequence of instances leading to
  the cell containing the selected object from the current cell) and the actual object selected.
  That information is combined into an ObjectInstPath object (<class_doc href="ObjectInstPath"/>).
  </p>

  <p>
  In our case we are not interested in the cell view that shape lives in. Neither are we in the instantiation path.
  Hence all we need is the shape and we can obtain it with the "shape" method. 
  This method delivers a Shape object (<class_doc href="Shape"/>), which is some kind of pointer (a "proxy") to the
  actual shape. The actual shape is either a polygon, a box, a text or a path. The Shape object has multiple
  identities and we can ask it what shape type is represents. For that, the Shape object offers methods like "is_box?" etc.
  If we know the type we can ask it for the actual object and fetch a Polygon (<class_doc href="Polygon"/>), a 
  Box (<class_doc href="Box"/>), a Text (<class_doc href="Text"/>) or a Path object (<class_doc href="Path"/>).
  For our sample however we don't need access to the actual object. 
  </p>

  <p>
  Finally we put together a message and display it in a message box:
  </p>

  <pre>  s = "Paths: #{paths}\n"
  s += "Polygons: #{polygons}\n"
  s += "Boxes: #{boxes}\n"
  s += "Texts: #{texts}\n"

  MessageBox::info("Shape Statistics", s, MessageBox::Ok)</pre>

  <p>
  MessageBox (<class_doc href="MessageBox"/>) is a class that provides modal message dialogs through 
  several class methods. "info" shows an information box and with the given title and message. The third
  parameter indicates which buttons will be shown. In that case, one "Ok" button is sufficient because 
  we don't want to take specific actions when the message box is closed. MessageBox is not the Qt class,
  which is also available (QMessageBox), but less portable in case a user does not have Qt binding enabled.
  </p>

  <p>
  This is just a simple example, but it already illustrates some basic concepts. 
  For a in-depth introduction into the API, read <link href="/programming/application_api.xml"/> and <link href="/programming/database_api.xml"/>.
  </p>

</doc>
  
