Commit ebaf1454 authored by Wayne Stambaugh's avatar Wayne Stambaugh

Add field removal warning to EESchema's edit component in schematic dialog.

* Warn the user that fields with no value and not it the field template list
  will be removed from the component before exiting the edit component in
  schematic dialog.
* Add a function to TEMPLATES class to check if template list contains a
  field with a given name.
* Move the function to display the edit component in schematic dialog into
  the SCH_EDIT_FRAME class.
* Doxygen and coding style policy fixes.
parent 3cc37e83
...@@ -25,21 +25,14 @@ int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_SelectedRow; ...@@ -25,21 +25,14 @@ int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_SelectedRow;
wxSize DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = wxDefaultSize; wxSize DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = wxDefaultSize;
void InstallCmpeditFrame( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent ) void SCH_EDIT_FRAME::EditComponent( SCH_COMPONENT* aComponent )
{ {
if( aComponent == NULL ) // Null component not accepted wxCHECK_RET( aComponent != NULL && aComponent->Type() == SCH_COMPONENT_T,
return; wxT( "Invalid component object pointer. Bad Programmer!" ) );
aParent->DrawPanel->m_IgnoreMouseEvents = TRUE;
if( aComponent->Type() != SCH_COMPONENT_T ) DrawPanel->m_IgnoreMouseEvents = true;
{
wxMessageBox( wxT( "InstallCmpeditFrame() error: This item is not a component" ) );
return;
}
DIALOG_EDIT_COMPONENT_IN_SCHEMATIC * dlg = DIALOG_EDIT_COMPONENT_IN_SCHEMATIC* dlg = new DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( this );
new DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( aParent );
dlg->InitBuffers( aComponent ); dlg->InitBuffers( aComponent );
...@@ -52,8 +45,7 @@ void InstallCmpeditFrame( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent ) ...@@ -52,8 +45,7 @@ void InstallCmpeditFrame( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent )
dlg->SetSize( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize ); dlg->SetSize( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize );
} }
// make sure the chipnameTextCtrl is wide enough to hold any // make sure the chipnameTextCtrl is wide enough to hold any unusually long chip names:
// unusually long chip names:
EnsureTextCtrlWidth( dlg->chipnameTextCtrl ); EnsureTextCtrlWidth( dlg->chipnameTextCtrl );
dlg->ShowModal(); dlg->ShowModal();
...@@ -63,8 +55,8 @@ void InstallCmpeditFrame( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent ) ...@@ -63,8 +55,8 @@ void InstallCmpeditFrame( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent )
// so it comes up wide enough next time. // so it comes up wide enough next time.
DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = dlg->GetSize(); DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = dlg->GetSize();
aParent->DrawPanel->MoveCursorToCrossHair(); DrawPanel->MoveCursorToCrossHair();
aParent->DrawPanel->m_IgnoreMouseEvents = false; DrawPanel->m_IgnoreMouseEvents = false;
dlg->Destroy(); dlg->Destroy();
} }
...@@ -168,14 +160,13 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions() ...@@ -168,14 +160,13 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions()
} }
} }
// For components with multiple shapes (De Morgan representation) Set the // For components with multiple shapes (De Morgan representation) Set the selected shape:
// selected shape:
if( convertCheckBox->IsEnabled() ) if( convertCheckBox->IsEnabled() )
{ {
m_Cmp->SetConvert( convertCheckBox->GetValue() ? 2 : 1 ); m_Cmp->SetConvert( convertCheckBox->GetValue() ? 2 : 1 );
} }
//Set the part selection in multiple part per pakcage //Set the part selection in multiple part per package
if( m_Cmp->GetUnit() ) if( m_Cmp->GetUnit() )
{ {
int unit_selection = unitChoice->GetCurrentSelection() + 1; int unit_selection = unitChoice->GetCurrentSelection() + 1;
...@@ -222,16 +213,18 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions() ...@@ -222,16 +213,18 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions()
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event ) void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event )
{ {
bool removeRemainingFields = false;
if( !copyPanelToSelectedField() ) if( !copyPanelToSelectedField() )
return; return;
if( ! SCH_COMPONENT::IsReferenceStringValid( m_FieldsBuf[REFERENCE].m_Text ) ) if( ! SCH_COMPONENT::IsReferenceStringValid( m_FieldsBuf[REFERENCE].m_Text ) )
{ {
DisplayError( NULL, _( "Illegal reference. A reference must start by a letter" ) ); DisplayError( NULL, _( "Illegal reference. A reference must start with a letter" ) );
return; return;
} }
// save old cmp in undo list if not already in edit, or moving ... // save old cmp in undo list if not already in edit, or moving ...
if( m_Cmp->m_Flags == 0 ) if( m_Cmp->m_Flags == 0 )
m_Parent->SaveCopyInUndoList( m_Cmp, UR_CHANGED ); m_Parent->SaveCopyInUndoList( m_Cmp, UR_CHANGED );
...@@ -243,12 +236,34 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event ...@@ -243,12 +236,34 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event
m_FieldsBuf[i].m_Pos += m_Cmp->m_Pos; m_FieldsBuf[i].m_Pos += m_Cmp->m_Pos;
} }
// delete any fields with no name or no value before we copy all of m_FieldsBuf // Delete any fields with no name before we copy all of m_FieldsBuf back into the component.
// back into the component
for( unsigned i = MANDATORY_FIELDS; i<m_FieldsBuf.size(); ) for( unsigned i = MANDATORY_FIELDS; i<m_FieldsBuf.size(); )
{ {
if( m_FieldsBuf[i].m_Name.IsEmpty() || m_FieldsBuf[i].m_Text.IsEmpty() ) if( m_FieldsBuf[i].m_Name.IsEmpty() || m_FieldsBuf[i].m_Text.IsEmpty() )
{ {
// If a field has no value and is not it the field template list, warn the user
// that it will be remove from the component. This gives the user a chance to
// correct the problem before removing the undefined fields. It should also
// resolve most of the bug reports and questions regarding missing fields.
if( !m_FieldsBuf[i].m_Name.IsEmpty() && m_FieldsBuf[i].m_Text.IsEmpty()
&& !m_Parent->GetTemplates().HasFieldName( m_FieldsBuf[i].m_Name )
&& !removeRemainingFields )
{
wxString msg;
msg.Printf( _( "The field name <%s> does not have a value and is not defined in \
the field template list. Empty field values are invalid an will be removed from the component. \
Do you wish to remove this and all remaining undefined fields?" ),
GetChars( m_FieldsBuf[i].m_Name ) );
wxMessageDialog dlg( this, msg, _( "Remove Fields" ), wxYES_NO | wxNO_DEFAULT );
if( dlg.ShowModal() == wxID_NO )
return;
removeRemainingFields = true;
}
m_FieldsBuf.erase( m_FieldsBuf.begin() + i ); m_FieldsBuf.erase( m_FieldsBuf.begin() + i );
continue; continue;
} }
...@@ -264,14 +279,14 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event ...@@ -264,14 +279,14 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event
// copy all the fields back, and change the length of m_Fields. // copy all the fields back, and change the length of m_Fields.
m_Cmp->SetFields( m_FieldsBuf ); m_Cmp->SetFields( m_FieldsBuf );
// Reference has a specific initialisation, depending on the current active sheet // Reference has a specific initialization, depending on the current active sheet
// because for a given component, in a complexe hierarchy, there are more than one // because for a given component, in a complex hierarchy, there are more than one
// reference. // reference.
m_Cmp->SetRef( m_Parent->GetSheet(), m_FieldsBuf[REFERENCE].m_Text ); m_Cmp->SetRef( m_Parent->GetSheet(), m_FieldsBuf[REFERENCE].m_Text );
m_Parent->OnModify(); m_Parent->OnModify();
m_Parent->GetScreen()->TestDanglingEnds(); m_Parent->GetScreen()->TestDanglingEnds();
m_Parent->DrawPanel->Refresh( TRUE ); m_Parent->DrawPanel->Refresh( true );
EndModal( 0 ); EndModal( 0 );
} }
...@@ -321,7 +336,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEven ...@@ -321,7 +336,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEven
if( fieldNdx >= m_FieldsBuf.size() ) if( fieldNdx >= m_FieldsBuf.size() )
--fieldNdx; --fieldNdx;
updateDisplay( ); updateDisplay();
setSelectedFieldNdx( fieldNdx ); setSelectedFieldNdx( fieldNdx );
m_skipCopyFromPanel = false; m_skipCopyFromPanel = false;
...@@ -357,7 +372,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::moveUpButtonHandler( wxCommandEvent& ev ...@@ -357,7 +372,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::moveUpButtonHandler( wxCommandEvent& ev
m_FieldsBuf[fieldNdx] = tmp; m_FieldsBuf[fieldNdx] = tmp;
setRowItem( fieldNdx, tmp ); setRowItem( fieldNdx, tmp );
updateDisplay( ); updateDisplay();
m_skipCopyFromPanel = true; m_skipCopyFromPanel = true;
setSelectedFieldNdx( fieldNdx - 1 ); setSelectedFieldNdx( fieldNdx - 1 );
...@@ -399,6 +414,7 @@ SCH_FIELD* DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::findField( const wxString& aField ...@@ -399,6 +414,7 @@ SCH_FIELD* DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::findField( const wxString& aField
if( aFieldName == m_FieldsBuf[i].m_Name ) if( aFieldName == m_FieldsBuf[i].m_Name )
return &m_FieldsBuf[i]; return &m_FieldsBuf[i];
} }
return NULL; return NULL;
} }
...@@ -449,6 +465,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent ...@@ -449,6 +465,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent
// Now copy in the template fields, in the order that they are present in the // Now copy in the template fields, in the order that they are present in the
// template field editor UI. // template field editor UI.
const TEMPLATE_FIELDNAMES& tfnames = m_Parent->GetTemplateFieldNames(); const TEMPLATE_FIELDNAMES& tfnames = m_Parent->GetTemplateFieldNames();
for( TEMPLATE_FIELDNAMES::const_iterator it = tfnames.begin(); it!=tfnames.end(); ++it ) for( TEMPLATE_FIELDNAMES::const_iterator it = tfnames.begin(); it!=tfnames.end(); ++it )
{ {
// add a new field unconditionally to the UI only // add a new field unconditionally to the UI only
...@@ -532,8 +549,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent ...@@ -532,8 +549,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent
} }
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setRowItem( int aFieldNdx, void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setRowItem( int aFieldNdx, const SCH_FIELD& aField )
const SCH_FIELD& aField )
{ {
wxASSERT( aFieldNdx >= 0 ); wxASSERT( aFieldNdx >= 0 );
...@@ -643,12 +659,10 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel() ...@@ -643,12 +659,10 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel()
// top of each other. // top of each other.
} }
wxString coordText = ReturnStringFromValue( g_UserUnit, coord.x, wxString coordText = ReturnStringFromValue( g_UserUnit, coord.x, EESCHEMA_INTERNAL_UNIT );
EESCHEMA_INTERNAL_UNIT );
posXTextCtrl->SetValue( coordText ); posXTextCtrl->SetValue( coordText );
coordText = ReturnStringFromValue( g_UserUnit, coord.y, coordText = ReturnStringFromValue( g_UserUnit, coord.y, EESCHEMA_INTERNAL_UNIT );
EESCHEMA_INTERNAL_UNIT );
posYTextCtrl->SetValue( coordText ); posYTextCtrl->SetValue( coordText );
} }
...@@ -689,10 +703,11 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField() ...@@ -689,10 +703,11 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField()
field.m_VJustify = vjustify[m_FieldVJustifyCtrl->GetSelection()]; field.m_VJustify = vjustify[m_FieldVJustifyCtrl->GetSelection()];
field.m_Name = fieldNameTextCtrl->GetValue(); field.m_Name = fieldNameTextCtrl->GetValue();
/* Void fields texts for REFERENCE and VALUE (value is the name of the /* Void fields texts for REFERENCE and VALUE (value is the name of the
* compinent in lib ! ) are not allowed * component in lib ! ) are not allowed
* change them only for a new non void value * change them only for a new non void value
* When woid, usually netlists are broken * When void, usually netlists are broken
*/ */
if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE ) if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE )
field.m_Text = fieldValueTextCtrl->GetValue(); field.m_Text = fieldValueTextCtrl->GetValue();
...@@ -798,13 +813,14 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel() ...@@ -798,13 +813,14 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
partsAreLockedLabel->Show( false ); partsAreLockedLabel->Show( false );
} }
// Positionnement de la reference en librairie // Set the component's library name.
chipnameTextCtrl->SetValue( m_Cmp->m_ChipName ); chipnameTextCtrl->SetValue( m_Cmp->m_ChipName );
} }
#include "kicad_device_context.h" #include "kicad_device_context.h"
/* reinitialize components parametres to default values found in lib /* reinitialize components parameters to default values found in lib
*/ */
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event ) void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event )
{ {
...@@ -836,7 +852,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event ) ...@@ -836,7 +852,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event )
m_Cmp->SetOrientation( CMP_NORMAL ); m_Cmp->SetOrientation( CMP_NORMAL );
m_Parent->OnModify( ); m_Parent->OnModify();
m_Cmp->Draw( m_Parent->DrawPanel, &dc, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); m_Cmp->Draw( m_Parent->DrawPanel, &dc, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
EndModal( 1 ); EndModal( 1 );
......
...@@ -8,6 +8,10 @@ ...@@ -8,6 +8,10 @@
#include "dialog_edit_component_in_schematic_fbp.h" #include "dialog_edit_component_in_schematic_fbp.h"
class SCH_EDIT_FRAME;
/** /**
* class DIALOG_EDIT_COMPONENT_IN_SCHEMATIC * class DIALOG_EDIT_COMPONENT_IN_SCHEMATIC
* is hand coded and implements DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP which * is hand coded and implements DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP which
...@@ -16,7 +20,7 @@ ...@@ -16,7 +20,7 @@
*/ */
class DIALOG_EDIT_COMPONENT_IN_SCHEMATIC : public DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP class DIALOG_EDIT_COMPONENT_IN_SCHEMATIC : public DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP
{ {
friend void InstallCmpeditFrame( SCH_EDIT_FRAME* parent, SCH_COMPONENT* aComponent ); friend class SCH_EDIT_FRAME;
SCH_EDIT_FRAME* m_Parent; SCH_EDIT_FRAME* m_Parent;
SCH_COMPONENT* m_Cmp; SCH_COMPONENT* m_Cmp;
......
...@@ -784,7 +784,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, ...@@ -784,7 +784,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition,
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case SCH_COMPONENT_T: case SCH_COMPONENT_T:
InstallCmpeditFrame( this, (SCH_COMPONENT*) aItem ); EditComponent( (SCH_COMPONENT*) aItem );
break; break;
case SCH_SHEET_T: case SCH_SHEET_T:
......
...@@ -332,7 +332,7 @@ void SCH_EDIT_FRAME::OnLeftDClick( wxDC* aDC, const wxPoint& aPosition ) ...@@ -332,7 +332,7 @@ void SCH_EDIT_FRAME::OnLeftDClick( wxDC* aDC, const wxPoint& aPosition )
break; break;
case SCH_COMPONENT_T: case SCH_COMPONENT_T:
InstallCmpeditFrame( this, (SCH_COMPONENT*) item ); EditComponent( (SCH_COMPONENT*) item );
DrawPanel->MoveCursorToCrossHair(); DrawPanel->MoveCursorToCrossHair();
break; break;
......
...@@ -31,11 +31,6 @@ wxString DataBaseGetName( EDA_DRAW_FRAME* frame, wxString& Keys, wxString& BufNa ...@@ -31,11 +31,6 @@ wxString DataBaseGetName( EDA_DRAW_FRAME* frame, wxString& Keys, wxString& BufNa
/*********************/ /*********************/
bool SegmentIntersect( wxPoint aSegStart, wxPoint aSegEnd, wxPoint aTestPoint ); bool SegmentIntersect( wxPoint aSegStart, wxPoint aSegEnd, wxPoint aTestPoint );
/****************/
/* EDITPART.CPP */
/****************/
void InstallCmpeditFrame( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent );
// operations_on_item_lists.cpp // operations_on_item_lists.cpp
void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList ); void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList );
......
...@@ -282,7 +282,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -282,7 +282,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
// Ensure the struct is a component (could be a struct of a // Ensure the struct is a component (could be a struct of a
// component, like Field, text..) // component, like Field, text..)
if( item && item->Type() == SCH_COMPONENT_T ) if( item && item->Type() == SCH_COMPONENT_T )
InstallCmpeditFrame( this, (SCH_COMPONENT*) item ); EditComponent( (SCH_COMPONENT*) item );
break; break;
......
...@@ -170,3 +170,15 @@ int TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName ) ...@@ -170,3 +170,15 @@ int TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName )
return m_Fields.size() - 1; // return the index of insertion. return m_Fields.size() - 1; // return the index of insertion.
} }
bool TEMPLATES::HasFieldName( const wxString& aName ) const
{
for( size_t i=0; i<m_Fields.size(); ++i )
{
if( m_Fields[i].m_Name == aName )
return true;
}
return false;
}
...@@ -145,6 +145,15 @@ public: ...@@ -145,6 +145,15 @@ public:
{ {
return m_Fields; return m_Fields;
} }
/**
* Function HasFieldName
* checks for \a aName in the the template field name list.
*
* @param aName A wxString object containing the field name to search for.
* @param True if \a aName is found in the list.
*/
bool HasFieldName( const wxString& aName ) const;
}; };
#endif // _TEMPLATE_FIELDNAME_H_ #endif // _TEMPLATE_FIELDNAME_H_
...@@ -207,6 +207,15 @@ public: ...@@ -207,6 +207,15 @@ public:
} }
/**
* Function GetTemplates
* returns the field names template for read only access.
*/
const TEMPLATES& GetTemplates()
{
return m_TemplateFieldNames;
}
/** /**
* Function DeleteAllTemplateFieldNames * Function DeleteAllTemplateFieldNames
* removes all template field names. * removes all template field names.
...@@ -736,6 +745,14 @@ private: ...@@ -736,6 +745,14 @@ private:
bool UseLibBrowser ); bool UseLibBrowser );
void StartMovePart( SCH_COMPONENT* DrawLibItem, wxDC* DC ); void StartMovePart( SCH_COMPONENT* DrawLibItem, wxDC* DC );
/**
* Function EditComponent
* displays the edit component dialog to edit the parameters of \a aComponent.
*
* @param aComponent is a pointer to the SCH_COMPONENT object to be edited.
*/
void EditComponent( SCH_COMPONENT* aComponent );
public: public:
void OnChangeComponentOrientation( wxCommandEvent& aEvent ); void OnChangeComponentOrientation( wxCommandEvent& aEvent );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment