Restoring a cellview

Dear KLayouters,

I am trying to save and restore the current view configuration (cell and zoom box), similar to how the File -> Reload menu item works: When reloading a GDS for example, the same cell with the same view (zoom box) is visible after as it was before reloading.

This is what I have so far:

    # try to save the current view
    current_cell_name = current_zoom_box = nil
    begin
      acv = RBA::CellView.active
      current_cell_name_path = acv.path.collect{|ci| acv.layout.cell(ci).name}
      current_zoom_box = RBA::LayoutView.current.box
    rescue
      puts("#{$!}\n#{$!.backtrace.join("\n")}")
    end

As you can see, I am saving the path as an array of cell names rather than cell indices to avoid problems if the cell indices change for some reason.

Then, with the new layout, I am trying to do the following:

    # try to restore the current view with the new layout
    begin
      cell_name_to_index = {}
      acv = RBA::CellView.active
      acv.layout.each_cell{|c| cell_name_to_index[c.name] = c.cell_index}
      acv.path = current_cell_name_path.collect{|name| cell_name_to_index[name]}
      RBA::LayoutView.current.zoom_box(current_zoom_box)
    rescue
      puts("#{$!}\n#{$!.backtrace.join("\n")}")
    end

This converts the array of names back to an array of indices with the new layout, sets the path of the currently activated cell and sets the zoom box back to where it was with the old layout.

Unfortunately, the line to restore the CellView.path

acv.path = current_cell_name_path.collect{|name| cell_name_to_index[name]}

fails with the following traceback:

Cannot call non-const on a const reference in CellView::path
  <main>:in `path='
  <main>:in `<main>'

Any clues as to what is going wrong here would be appreciated.

Comments

  • edited November -1

    Ah, seems like I was simply using the wrong method on the wrong object. Here is the fixed version, which works nicely:

        # try to restore the current view with the new layout
        begin
          cell_name_to_index = {}
          acv = RBA::CellView.active
          acv.layout.each_cell{|c| cell_name_to_index[c.name] = c.cell_index}
          cell_index_path = current_cell_name_path.collect{|name| cell_name_to_index[name]}
          cv_index = RBA::LayoutView.current.active_cellview_index
          RBA::LayoutView.current.set_current_cell_path(cv_index, cell_index_path)
          RBA::LayoutView.current.select_cell_path(cell_index_path, cv_index)
          RBA::LayoutView.current.zoom_box(current_zoom_box)
        rescue
          puts("#{$!}\n#{$!.backtrace.join("\n")}")
        end
    

    I will extend this to also match the currently visible layers and number of hierarchy levels and post the code once I have it working.

    Regards, Chris

  • edited June 2015

    It may not be the most elegant, but I think the easiest way to restore the layer properties is to save them to a temporary file and load that file on the new layout.

    Here is the code which will query the currently visible cell and view area, hierarchy levels and layer settings:

        # try to save the current view
        current_cell_name = current_zoom_box = current_max_hier_levels = current_layer_properties_temp_file = nil
        begin
          acv = RBA::CellView.active
          clv = RBA::LayoutView.current
          current_cell_name_path = acv.path.collect{|ci| acv.layout.cell(ci).name}
          current_zoom_box = clv.box
          current_max_hier_levels = clv.max_hier_levels
          require 'tempfile'
          current_layer_properties_temp_file = Tempfile.new('KLayout-current_layer_properties')
          current_layer_properties_temp_file.close
          clv.save_layer_props(current_layer_properties_temp_file.path)
        rescue
          puts("#{$!}\n#{$!.backtrace.join("\n")}")
        end
    

    And here the code to restore all of that on a new layout:

        # try to restore the current view with the new layout
        begin
          cell_name_to_index = {}
          acv = RBA::CellView.active
          clv = RBA::LayoutView.current
          acv.layout.each_cell{|c| cell_name_to_index[c.name] = c.cell_index}
          cell_index_path = current_cell_name_path.collect{|name| cell_name_to_index[name]}
          cv_index = clv.active_cellview_index
          clv.set_current_cell_path(cv_index, cell_index_path)
          clv.select_cell_path(cell_index_path, cv_index)
          clv.zoom_box(current_zoom_box)
          clv.max_hier_levels = current_max_hier_levels
          clv.load_layer_props(current_layer_properties_temp_file.path)
        rescue
          puts("#{$!}\n#{$!.backtrace.join("\n")}")
        ensure
          current_layer_properties_temp_file.unlink unless current_layer_properties_temp_file.nil?
        end
    

    If you know how to copy the layer settings easily without having to create a temporary file, I'd be happy to hear about it.

    Regards, Chris

  • edited November -1

    Hi Chris,

    regarding the path assignment: the CellView object is not directly linked to the actual view. It's a descriptor object which you can't modify, hence direct assignment of the path is not possible. But I admit that would we very intuitive. Right now, the only way to change the cell path is the one you found.

    A way to save/restore the layer properties is to retrieve them through the iterator delivered by LayoutView#begin_layers, create a copy of these objects and restore them later. But on the other hand, the temporary file approach is much easier to implement.

    Have you had a look into the "sessions" concept? The intention of that feature is to save a session and restore it later. It's based on "session" files which keep layer properties and the zoom box. In addition these files also store the images added to the views and the rulers.

    Would it be helpful to have a way to save and load such files from a scripts?

    Matthias

  • edited June 2015

    Hi Matthias,

    Thanks for pointing me to the "sessions" feature, I wasn't aware of that.

    My use case for restoring the current view is very similar to the one that you currently have implemented in the File -> Reload menu item, just instead of reloading a GDS file, in my case a Ruby script (which generates a layout on the fly) is re-executed after which I'd like to restore the view. So I guess the question becomes: Which mechanism does KLayout use under the hood to re-create the current view with the reloaded layout? Ideally, a script could just hook into that, but for the moment, the code I posted earlier seems to work nicely.

    If there was a way to save just one "session" file from a script and reload it (rather than having to save & reload the layer properties and keeping the additional current_cell_name, current_zoom_box and current_max_hier_levels variables), I'd probably use that, but for now the above solution works. I am wondering about sessions if they could (maybe in the future) also restore multiple panels in one step, in which case they wouldn't fit my use case.

    the CellView object is not directly linked to the actual view. It's a descriptor object which you can't modify, hence direct assignment of the path is not possible. But I admit that would we very intuitive.

    Since there is a way to set the view that works (namely through the LayoutView object), I think there is no need for another way to set it through a CellView instance.

    Therefore it is probably just

    • a documentation issue since it describes a CellView#path= method,
    • an API generation issue (in that this method gets included in the CellView class even though path should be read-only) or
    • a combination of both.

    Either way, I am happy there is a workaround and guess the easiest solution is just to remove the documentation of CellView#path= from the documentation.

    Thanks for your time!

    Regards, Chris

  • edited November -1

    Hi Chris,

    session loading and restoring is actually available already (MainWindow#save_session and MainWindow#restore_session). I just forgot that feature.

    Regarding the CellView: actually, CellView is an object on it's own and basically is something like a descriptor. In the future it may be possible to use it separately, hence attribute readers and writers are there. Right now, it's only useful when returned from a LayoutView - and then it's a read-only reference (in C++: a const CellView *.

    Regards,

    Matthias

Sign In or Register to comment.