HowToCommunicateBtwProcessorAndPanelWidget

From user's Wiki!
Jump to: navigation, search

This page provides some tips and standards on how to handle the info between a GIMIAS Processor and its corresponding PanelWidget.

Structure

In a Gimias Plugin there are two different layers, the PanelWidget (GUI layer) and the Processor (Non GUI layer). The first one is dedicated to the interface and to whatever is connected to the rendering of the dataEntities. The second one is dedicated to the definition of inputs/outputs of the process we want to implement and to its implementation . How are these two layers connected and how can they communicate between them?

Information from Processor to PanelWidget

Inputs

There is an automatic generation of GUI that depends on the Processor. The inputs that are created in the Processor (see page Input and Output handling in GIMIAS Processors) are automatically added as GUI elements in the Panel Widget. In the order they will be declared in the Processor. By default they will automatically select the corresponding dataEntity that is present in the list, and always by default they will change the selection whenever a new dataEntity, that is compatible with the type they own, will be selected.

If we don't want this default values or if we want to hide the input from the GUI we can do this in the OnInit() function of PanelWidget :

GetInputWidget(INPUT_ID)->Hide();                            // To hide the widget
GetInputWidget(INPUT_ID)->SetAutomaticSelection(false);      // Not to have the automatic selection
GetInputWidget(INPUT_ID)->SetDefaultDataEntityFlag(false);   // Not to have default dataEntity (you have to choose which dataEntity)

Inputs.PNG

Outpus

If in the WidgetCollective where our PanelWidget is declared there is the option "ProcessorObservers()" (that is the automatic option you have when you create your Plugin with StartNewModule)

Core::WindowConfig config;
	config.ProcessorObservers().TabPage( "MyPluginTab" ).CommandPanel(); 

There is an automatic publishing of the output hides the input and it renders the output. You make add some changes to this features by adding these lines to the OnInit() function of your PanelWidget:

GetProcessorOutputObserver(ID)->SetHideInput(false);                   // Not to hide the input
GetProcessorOutputObserver(ID)->SelectDataEntity(false);               // Not to select the output
GetProcessorOutputObserver(ID)->SetOpacityInput(true, InputID, 0.5);   // To Set the opacity of the input to a specific value

For Advanced Users only : But if you really want to handle your own publishing of the outputs as you prefer (Set Colors, particular rendering...) you have to do two steps:

1. Add observers to your input/output (in the OnInit() function )

2. Implement the rendering and hide/show properties

// Observers to data
m_Processor->GetOutputDataEntityHolder(0 )->AddObserver( 
             this, 
             &PanelWidget::OnModifiedOutputDataEntity );
void MyPlugin::MyFuncPanelWidget::OnModifiedOutputDataEntity()
{
	try{

		Core::DataEntity::Pointer inputDataEntity;
		inputDataEntity = m_Processor->GetInputDataEntity( 0 );

		// Hide input if is different from output and output is not empty
		if ( m_Processor->GetOutputDataEntity( 0 ).IsNotNull() && 
			 m_Processor->GetOutputDataEntity( 0 ) != inputDataEntity )
		{
			GetRenderingTree( )->Show( inputDataEntity, false );
		}

		// Add output to the data list and render it
		Core::DataTreeHelper::PublishOutput( 
			m_Processor->GetOutputDataEntityHolder(0 ), 
			GetRenderingTree() );
	}
	coreCatchExceptionsLogAndNoThrowMacro( 
		"PanelWidget::OnModifiedOutputDataEntity")

}

Parameters

If we want to give to the PanelWidget the values that have been computed in the processor we can use the UpdateWidget() function that we will call after the Processor Update() function. In this function there will be:

text_ctrl_param->SetValue(wxString::Format(wxT("%.2f"), m_Processor->GetParam() ) ); 

Remember that almost every time the Values that you put in the GUI are WxString, so we will have to convert the double, float, bool, int values we have into WxString.

Information from PanelWidget to Processor

Parameters

If we want to give to the Processor the values that have been taped in the interface we can use the UpdateData() function that we will call before the Processor Update() function. In this function there will be something like:

m_Processor->SetParam(std::atof(text_ctrl_param->GetValue()));

For Advanced Users only: In case we want to Update every time we change a value in the interface we have to use a variable that we will put in the header of our PanelWidget

#include "gblWxConnectorOfWidgetChangesToSlotFunction.h"
//!
gbl::wx::ConnectorOfWidgetChangesToSlotFunction changeInWidgetObserver;

And that we will initialize in this way :

changeInWidgetObserver.SetSlotFunction(this, &PanelWidget::UpdateData);
changeInWidgetObserver.Observe(text_ctrl_param);

And in the UpdateWidget function you will have to disable/enable the observer in order to change the values like this:

changeInWidgetObserver.SetEnabled(false);
text_ctrl_param->SetValue(wxString::Format(wxT("%.2f"), m_Processor->GetParam() ) );

wxGlade

When designing your panel widget, you can use wxGlade. You can see the panel widget SandboxPluginShapeScalePanelWidget as an example.


These are the main issues to consider when using wxGlade:

  • Design: Use the feature "Overwrite existing sources" and generate the files with an UI post fix in the file name, like for example SandboxPluginShapeScalePanelWidgetUI. You can find this option in the node "Application".
  • Custom code: Create your own derived class when you need to add custom code (SandboxPluginShapeScalePanelWidget)
  • Control identifiers: When handling events from several controls, you need to use an identifier for each control.
    • Create the identifiers in the "Code" page of your panel widget node, enabling the option "Extra code for this widget". The code should look like this:
#include "wxID.H"
#define wxID_BTN_SCALE wxID("SandboxPluginShapeScalePanelWidgetUIBtnScale")
    • Use the identifier in your control. For example, if you click on the control wxButton, you will find the option Id clicked with the value wxID_BTN_SCALE
  • Event handler
    • Define the event handler function in the "Events" page of your control node. For example, if you add a wxButton and click on the Event page, you will see the Event EVT_BUTTON with an empty cell next to it. Click on the empty cell and set the name of you handler function (OnBtnScale)
    • If you open the generated UI.h file, you will find the handler function. You need to override this function in your own class (SandboxPluginShapeScalePanelWidget):
virtual void OnBtnScale(wxCommandEvent &event); // wxGlade: <event_handler>

Go back to Developers