Add button to maximize view

@lassoan

  • For accessing qMRMLLayoutManager::setLayout function in qMRMLThreeDViewControllerWidget, I need an instance of qMRMLLayoutManager.

  • So, how can I get the qMRMLLayoutManager instance in qMRMLThreeDViewControllerWidget. Or is there any other way of accessing qMRMLLayoutManager::setLayout.

How this should probably work is that the widget would set a maximizedLayoutName (layout name of the maximized view) in the vtkMRMLLayoutNode. You can get the layout node from the scene: if ParentLayoutNode is set in the view node then you will use that node, otherwise you will look up the default layout manager node (it is a singleton).

The layout manager gets a notification about the layout node change and it will hide all layout elements from the view except the widget that corresponds to maximizedLayoutName.

Instead of creating a new function (maximizedLayoutName) there is already a setLayout function in qMRMLLayoutManager. Will there be any problem if I use that?

code:

void qMRMLLayoutManager::setLayout(int layout)
{
  Q_D(qMRMLLayoutManager);
  if (this->layout() == layout)
    {
    return;
    }
  // Update LayoutNode
  if (d->MRMLLayoutNode)
    {
    if (!d->MRMLLayoutNode->IsLayoutDescription(layout))
      {
      layout = vtkMRMLLayoutNode::SlicerLayoutConventionalView;
      }
    d->MRMLLayoutNode->SetViewArrangement(layout);
    }
}

MRMLLayoutNode is a pointer of vtkMRMLLayoutNode* MRMLLayoutNode;

code for IsLayoutDescription in vtkMRMLLayoutNode:

bool vtkMRMLLayoutNode::IsLayoutDescription(int layout)
{
  std::map<int, std::string>::const_iterator it = this->Layouts.find(layout);
  return it != this->Layouts.end();
}

code for SetViewArrangement in vtkMRMLLayoutNode:

void vtkMRMLLayoutNode::SetViewArrangement(int arrNew)
{
 // if the view arrangement definition has not been changed, return
 if ( this->ViewArrangement == arrNew
   && this->GetCurrentLayoutDescription()
   && this->GetCurrentLayoutDescription() == this->GetLayoutDescription(arrNew) )
   {
   return;
   }
 this->ViewArrangement = arrNew;
#if 1
 if (!this->IsLayoutDescription(this->ViewArrangement))
   {
   vtkWarningMacro(<< "View arrangement " << this->ViewArrangement
                   << " is not recognized, register it with "
                   << "AddLayoutDescription()");
   }
#endif
 int wasModifying = this->StartModify();
 this->UpdateCurrentLayoutDescription();
 this->Modified();
 this->EndModify(wasModifying);
}

Maximizing a view is a temporary operation. It should be possible to maximize/restore a selected view without changing the layout.

1 Like
  • How can I create an instance of qMRMLLayoutManager in qMRMLThreeDViewControllerWidget.

@lassoan

  • For accessing vtkMRMLLayoutNode I need an instance, and I can’t figure out how to initialize vtkMRMLLayoutNode pointer.

The qMRMLThreeDViewControllerWidget does not know how many layout managers the application has or how to access them. But it can get the vtkMRMLLayoutNode from the scene, because if its view node’s ParentLayoutNode is nullptr (most of the cases, except when a view is shown outside of the layout) then you can look up the vtkMRMLLayoutNode by its singleton tag (scene->GetSingletonNode("vtkMRMLLayoutNode","vtkMRMLLayoutNode")). When you change the MaximizedLayoutName property then the layout manager will detect the change and act accordingly. You need to add the new MaximizedLayoutName property to vtkMRMLLayoutNode, along with GetMaximizedLayoutName and SetMaximizedLayoutName methods to get/set it.

1 Like

I see that you marked the above answer as Stilton. Did this mean that you are going to implement the temporary maximize/restore view feature or you just switch layouts?

I already implemented maximizing/minimizing feature but by using switching layouts

code for 3D Layout:

    int layout_3D = vtkMRMLLayoutNode::SlicerLayoutOneUp3DView;
    int layout_FourUp = vtkMRMLLayoutNode::SlicerLayoutFourUpView;
    vtkMRMLLayoutNode* layoutNode = vtkMRMLLayoutNode::SafeDownCast(this->mrmlScene()->GetSingletonNode("vtkMRMLLayoutNode", "vtkMRMLLayoutNode"));
    if (layoutNode)
    {
        if (!maximumView_ThreeDView) {
            layoutNode->SetViewArrangement(layout_3D);
            maximumView_ThreeDView = true;
            d->actionCenter->setToolTip("Minimize");
        }
        else {
            layoutNode->SetViewArrangement(layout_FourUp);
            maximumView_ThreeDView = false;
            d->actionCenter->setToolTip("Maximize");
        }
    }

code for Axial, sagittal, cornal:

    QString x = d->ViewLabel->text();
    int layout = vtkMRMLLayoutNode::SlicerLayoutFourUpView;
    int layout_Red = vtkMRMLLayoutNode::SlicerLayoutOneUpRedSliceView;
    int layout_Yellow = vtkMRMLLayoutNode::SlicerLayoutOneUpYellowSliceView;
    int layout_Green = vtkMRMLLayoutNode::SlicerLayoutOneUpGreenSliceView;

    vtkMRMLLayoutNode* layoutNode = vtkMRMLLayoutNode::SafeDownCast(this->mrmlScene()->GetSingletonNode("vtkMRMLLayoutNode", "vtkMRMLLayoutNode"));
    if (layoutNode) {
        if (x.contains("R")) {
            if (!maximumView) {
                layoutNode->SetViewArrangement(layout_Red);
                maximumView = true;
                d->actionFit_to_window->setToolTip("Minimize");
            }
            else
            {
                layoutNode->SetViewArrangement(layout);
                maximumView = false;
                d->actionFit_to_window->setToolTip("Maximize");
            }
        }
        else if (x.contains("G")) {
            if (!maximumView) {
                layoutNode->SetViewArrangement(layout_Green);
                maximumView = true;
                d->actionFit_to_window->setToolTip("Minimize");
            }
            else
            {
                layoutNode->SetViewArrangement(layout);
                maximumView = false;
                d->actionFit_to_window->setToolTip("Maximize");
            }
        }
        else if (x.contains("Y")) {
            if (!maximumView) {
                layoutNode->SetViewArrangement(layout_Yellow);
                maximumView = true;
                d->actionFit_to_window->setToolTip("Minimize");
            }
            else
            {
                layoutNode->SetViewArrangement(layout);
                maximumView = false;
                d->actionFit_to_window->setToolTip("Maximize");
            }
        }
    }

And this method works, but please let me know if this is the right way to do or not.

Thank you for sharing. This can work for a custom application where to have full control over what view layouts you allow your user to choose. However, this is not a general solution that could be used in Slicer core for several reasons. For example, there is no one-up layout for every view.

For implementing “temporary maximize/restore view feature”

void vtkMRMLLayoutNode::SetMaximizedLayoutName(const char *MaximizedLayoutName)
{
  //do something
}

const char *vtkMRMLLayoutNode::GetMaximizedLayoutName()
{
  //do something
}

After this I am unable to proceed.

Basically I am not able figure out how to notify qMRMLLayoutManager to change the layout.

Were you able to solve this or you have given up on this? Let us know if you are still interested in implementing this and need help.

Yes, I am still interested in implementing this, but need some help.

For implementing “temporary maximize/restore view feature”

void vtkMRMLLayoutNode::SetMaximizedLayoutName(const char *MaximizedLayoutName)
{
  //do something
}

const char *vtkMRMLLayoutNode::GetMaximizedLayoutName()
{
  //do something
}

After this, I am unable to proceed.

In these methods you would just store the name of the layout. Note that the “layout” word can unfortunately used for two different things: A. name of a view arrangement, B. name of a view within a view arrangement (LayoutName property of a view node). In this case “LayoutName” refers to B (the variable stores the name of a view).

You don’t need to write the implementation of these methods, you can just add these lines to vtkMRMLLayoutNode.h:

vtkGetStringMacro(MaximizedLayoutName);
vtkSetStringMacro(MaximizedLayoutName);

and create and initialize and delete the member variable:

  • in the header: declare const char* MaximizedLayoutName
  • in the constructor set this->MaximizedLayoutName = nullptr;
  • in the destructor call this->SetMaximizedLayoutName(nullptr);

After this, you need to implement in layoutmanager to observe this MaximizedLayoutName property and hiding of views in CTK.

Would it make sense to add an entry to the glossary ?

1 Like