#include #include #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "class_drawpanel.h" #include "confirm.h" #include "program.h" #include "general.h" #include "protos.h" #include "class_library.h" #include "dialog_edit_component_in_schematic.h" int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_SelectedRow; wxSize DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = wxDefaultSize; /**********************************************************************/ void InstallCmpeditFrame( WinEDA_SchematicFrame* parent, wxPoint& pos, SCH_COMPONENT* aComponent ) /*********************************************************************/ { if( aComponent == NULL ) // Null component not accepted return; parent->DrawPanel->m_IgnoreMouseEvents = TRUE; if( aComponent->Type() != TYPE_SCH_COMPONENT ) { DisplayError( parent, wxT( "InstallCmpeditFrame() error: This item is not a component" ) ); } else { DIALOG_EDIT_COMPONENT_IN_SCHEMATIC* dialog = new DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( parent ); dialog->InitBuffers( aComponent ); wxSize sizeNow = dialog->GetSize(); // this relies on wxDefaultSize being -1,-1, be careful here. if( sizeNow.GetWidth() < DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize.GetWidth() || sizeNow.GetHeight() < DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize.GetHeight() ) { dialog->SetSize( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize ); } // make sure the chipnameTextCtrl is wide enough to hold any unusually long chip names: EnsureTextCtrlWidth( dialog->chipnameTextCtrl ); dialog->ShowModal(); // Some of the field values are long and are not always fully visible // because the window comes up too narrow. // Remember user's manual window resizing efforts here so it comes up wide enough next time. DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = dialog->GetSize(); dialog->Destroy(); } parent->DrawPanel->MouseToCursorSchema(); parent->DrawPanel->m_IgnoreMouseEvents = false; } DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( wxWindow* parent ) : DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP( parent ) { m_Parent = (WinEDA_SchematicFrame*) parent; m_LibEntry = NULL; m_skipCopyFromPanel = false; wxListItem columnLabel; columnLabel.SetImage( -1 ); columnLabel.SetText( _( "Name" ) ); fieldListCtrl->InsertColumn( 0, columnLabel ); columnLabel.SetText( _( "Value" ) ); fieldListCtrl->InsertColumn( 1, columnLabel ); wxString label = _( "Size" ) + ReturnUnitSymbol( g_UnitMetric ); textSizeLabel->SetLabel( label ); label = _( "Pos " ); label += _( "X" ); label += ReturnUnitSymbol( g_UnitMetric ); posXLabel->SetLabel( label ); label = _( "Pos " ); label += _( "Y" ); label += ReturnUnitSymbol( g_UnitMetric ); posYLabel->SetLabel( label ); copySelectedFieldToPanel(); wxToolTip::Enable( true ); if( GetSizer() ) { GetSizer()->SetSizeHints( this ); } } /******************************************************************************/ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::reinitializeFieldsIdAndDefaultNames( ) /*****************************************************************************/ { for( unsigned new_id = FIELD1; new_id < m_FieldsBuf.size(); new_id++ ) { unsigned old_id = m_FieldsBuf[new_id].m_FieldId; if ( old_id != new_id ) { if ( m_FieldsBuf[new_id].m_Name == ReturnDefaultFieldName( old_id ) ) m_FieldsBuf[new_id].m_Name = ReturnDefaultFieldName( new_id ); m_FieldsBuf[new_id].m_FieldId = new_id; } } } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemDeselected( wxListEvent& event ) { D( printf( "OnListItemDeselected()\n" ); ) if( !m_skipCopyFromPanel ) { if( !copyPanelToSelectedField() ) event.Skip(); // do not go to the next row } } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemSelected( wxListEvent& event ) { D( printf( "OnListItemSelected()\n" ); ) // remember the selected row, statically s_SelectedRow = event.GetIndex(); copySelectedFieldToPanel(); } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnCancelButtonClick( wxCommandEvent& event ) { EndModal( 1 ); } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions() { wxString newname = chipnameTextCtrl->GetValue(); newname.MakeUpper(); newname.Replace( wxT( " " ), wxT( "_" ) ); if( newname.IsEmpty() ) DisplayError( this, _( "No Component Name!" ) ); else if( newname.CmpNoCase( m_Cmp->m_ChipName ) ) { if( CMP_LIBRARY::FindLibraryEntry( newname ) == NULL ) { wxString message; message.Printf( _( "Component [%s] not found!" ), newname.GetData() ); DisplayError( this, message ); } else // Change component from lib! { m_Cmp->m_ChipName = newname; } } // For components with multiple shapes (De Morgan representation) Set the selected shape: if( convertCheckBox->IsEnabled() ) { m_Cmp->m_Convert = convertCheckBox->GetValue() ? 2 : 1; } //Set the part selection in multiple part per pakcage if( m_Cmp->m_Multi ) { int unit_selection = unitChoice->GetCurrentSelection() + 1; m_Cmp->SetUnitSelection( m_Parent->GetSheet(), unit_selection ); m_Cmp->m_Multi = unit_selection; } switch( orientationRadioBox->GetSelection() ) { case 0: m_Cmp->SetRotationMiroir( CMP_ORIENT_0 ); break; case 1: m_Cmp->SetRotationMiroir( CMP_ORIENT_90 ); break; case 2: m_Cmp->SetRotationMiroir( CMP_ORIENT_180 ); break; case 3: m_Cmp->SetRotationMiroir( CMP_ORIENT_270 ); break; } int mirror = mirrorRadioBox->GetSelection(); switch( mirror ) { case 0: break; case 1: m_Cmp->SetRotationMiroir( CMP_MIROIR_X ); break; case 2: m_Cmp->SetRotationMiroir( CMP_MIROIR_Y ); break; } } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event ) { if( !copyPanelToSelectedField() ) return; copyPanelToOptions(); /* save old cmp in undo list if not already in edit, or moving ... */ if( m_Cmp->m_Flags == 0 ) m_Parent->SaveCopyInUndoList( m_Cmp, UR_CHANGED ); // change all field positions from relative to absolute for( unsigned i = 0; im_Pos; } // delete any fields with no name for( unsigned i = FIELD1; im_ChipName ); if( entry && entry->m_Options == ENTRY_POWER ) m_FieldsBuf[VALUE].m_Text = m_Cmp->m_ChipName; // copy all the fields back, and change the length of m_Fields. m_Cmp->SetFields( m_FieldsBuf ); m_Parent->GetScreen()->SetModify(); m_Parent->TestDanglingEnds( m_Parent->GetScreen()->EEDrawList, NULL ); m_Parent->DrawPanel->Refresh( TRUE ); EndModal( 0 ); } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::addFieldButtonHandler( wxCommandEvent& event ) { // in case m_FieldsBuf[REFERENCE].m_Orient has changed on screen only, grab // screen contents. if( !copyPanelToSelectedField() ) return; unsigned fieldNdx = m_FieldsBuf.size(); SCH_CMP_FIELD blank( wxPoint(), fieldNdx, m_Cmp ); blank.m_Orient = m_FieldsBuf[REFERENCE].m_Orient; m_FieldsBuf.push_back( blank ); m_FieldsBuf[fieldNdx].m_Name = ReturnDefaultFieldName(fieldNdx); m_skipCopyFromPanel = true; setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] ); setSelectedFieldNdx( fieldNdx ); m_skipCopyFromPanel = false; } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEvent& event ) { unsigned fieldNdx = getSelectedFieldNdx(); if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too return; if( fieldNdx < FIELD1 ) { wxBell(); return; } m_skipCopyFromPanel = true; m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx ); fieldListCtrl->DeleteItem( fieldNdx ); if( fieldNdx >= m_FieldsBuf.size() ) --fieldNdx; // Reinitialize fields IDs and default names: reinitializeFieldsIdAndDefaultNames(); updateDisplay( ); setSelectedFieldNdx( fieldNdx ); m_skipCopyFromPanel = false; } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC:: moveUpButtonHandler( wxCommandEvent& event ) { unsigned fieldNdx = getSelectedFieldNdx(); if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too return; if( fieldNdx <= FIELD1 ) { wxBell(); return; } if( !copyPanelToSelectedField() ) return; // swap the fieldNdx field with the one before it, in both the vector // and in the fieldListCtrl SCH_CMP_FIELD tmp = m_FieldsBuf[fieldNdx - 1]; D( printf( "tmp.m_Text=\"%s\" tmp.m_Name=\"%s\"\n", CONV_TO_UTF8( tmp.m_Text ), CONV_TO_UTF8( tmp.m_Name ) ); ) m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx]; setRowItem( fieldNdx - 1, m_FieldsBuf[fieldNdx] ); m_FieldsBuf[fieldNdx] = tmp; setRowItem( fieldNdx, tmp ); // Reinitialize fields IDs and default names: reinitializeFieldsIdAndDefaultNames(); updateDisplay( ); m_skipCopyFromPanel = true; setSelectedFieldNdx( fieldNdx - 1 ); m_skipCopyFromPanel = false; } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setSelectedFieldNdx( int aFieldNdx ) { /* deselect old selection, but I think this is done by single selection flag within fieldListCtrl * fieldListCtrl->SetItemState( s_SelectedRow, 0, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED); */ if( aFieldNdx >= (int) m_FieldsBuf.size() ) aFieldNdx = m_FieldsBuf.size() - 1; if( aFieldNdx < 0 ) aFieldNdx = 0; fieldListCtrl->SetItemState( aFieldNdx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); fieldListCtrl->EnsureVisible( aFieldNdx ); s_SelectedRow = aFieldNdx; } int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::getSelectedFieldNdx() { return s_SelectedRow; } static bool SortFieldsById(const SCH_CMP_FIELD& item1, const SCH_CMP_FIELD& item2) { return item1.m_FieldId < item2.m_FieldId; } /*******************************************************************************/ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent ) /*******************************************************************************/ { m_Cmp = aComponent; m_LibEntry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName ); #if 0 && defined(DEBUG) for( int i = 0; iGetFieldCount(); ++i ) { printf( "Orig[%d] (x=%d, y=%d)\n", i, aComponent->m_Fields[i].m_Pos.x, aComponent->m_Fields[i].m_Pos.y ); } #endif // copy all the fields to a work area m_FieldsBuf = aComponent->m_Fields; // Sort files by field id,if they are not entered by id sort(m_FieldsBuf.begin(), m_FieldsBuf.end(), SortFieldsById); #if 0 && defined(DEBUG) for( unsigned i = 0; iGetRef( m_Parent->GetSheet() ); for( unsigned i = 0; im_Pos; setRowItem( i, m_FieldsBuf[i] ); } #if 0 && defined(DEBUG) for( unsigned i = 0; iSetFocus(); // resume editing at the last row edited, last time dialog was up. setSelectedFieldNdx( s_SelectedRow ); } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setRowItem( int aFieldNdx, const SCH_CMP_FIELD& aField ) { wxASSERT( aFieldNdx >= 0 ); // insert blanks if aFieldNdx is referencing a "yet to be defined" row while( aFieldNdx >= fieldListCtrl->GetItemCount() ) { long ndx = fieldListCtrl->InsertItem( fieldListCtrl->GetItemCount(), wxEmptyString ); wxASSERT( ndx >= 0 ); fieldListCtrl->SetItem( ndx, 1, wxEmptyString ); } fieldListCtrl->SetItem( aFieldNdx, 0, aField.m_Name ); fieldListCtrl->SetItem( aFieldNdx, 1, aField.m_Text ); // recompute the column widths here, after setting texts fieldListCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE ); fieldListCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE ); } /****************************************************************/ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel() /****************************************************************/ { unsigned fieldNdx = getSelectedFieldNdx(); if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too return; SCH_CMP_FIELD& field = m_FieldsBuf[fieldNdx]; showCheckBox->SetValue( !(field.m_Attributs & TEXT_NO_VISIBLE) ); rotateCheckBox->SetValue( field.m_Orient == TEXT_ORIENT_VERT ); int style = 0; if( field.m_Italic ) style = 1; if( field.m_Bold ) style |= 2; m_StyleRadioBox->SetSelection( style ); fieldNameTextCtrl->SetValue( field.m_Name ); // if fieldNdx == REFERENCE, VALUE, FOOTPRINT, or DATASHEET, then disable editing fieldNameTextCtrl->Enable( fieldNdx >= FIELD1 ); fieldNameTextCtrl->SetEditable( fieldNdx >= FIELD1 ); moveUpButton->Enable( fieldNdx >= FIELD1 ); // disable move up button for non moveable fields // if fieldNdx == REFERENCE, VALUE, then disable delete button deleteFieldButton->Enable( fieldNdx > VALUE ); fieldValueTextCtrl->SetValue( field.m_Text ); // For power symbols, the value is NOR editable, because value and pin name must be same // and can be edited only in library editor if( fieldNdx == VALUE && m_LibEntry && m_LibEntry->m_Options == ENTRY_POWER ) fieldValueTextCtrl->Enable( false ); else fieldValueTextCtrl->Enable( true ); textSizeTextCtrl->SetValue( WinEDA_GraphicTextCtrl::FormatSize( EESCHEMA_INTERNAL_UNIT, g_UnitMetric, field.m_Size.x ) ); wxPoint coord = field.m_Pos; wxPoint zero = -m_Cmp->m_Pos; // relative zero // If the field value is empty and the position is at relative zero, we set the // initial position as a small offset from the ref field, and orient // it the same as the ref field. That is likely to put it at least // close to the desired position. if( coord == zero && field.m_Text.IsEmpty() ) { rotateCheckBox->SetValue( m_FieldsBuf[REFERENCE].m_Orient == TEXT_ORIENT_VERT ); coord.x = m_FieldsBuf[REFERENCE].m_Pos.x + (fieldNdx - FIELD1 + 1) * 100; coord.y = m_FieldsBuf[REFERENCE].m_Pos.y + (fieldNdx - FIELD1 + 1) * 100; // coord can compute negative if field is < FIELD1, e.g. FOOTPRINT. // That is ok, we basically don't want all the new empty fields on // top of each other. } wxString coordText = ReturnStringFromValue( g_UnitMetric, coord.x, EESCHEMA_INTERNAL_UNIT ); posXTextCtrl->SetValue( coordText ); coordText = ReturnStringFromValue( g_UnitMetric, coord.y, EESCHEMA_INTERNAL_UNIT ); posYTextCtrl->SetValue( coordText ); } /*****************************************************************/ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField() /*****************************************************************/ { unsigned fieldNdx = getSelectedFieldNdx(); if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too return true; SCH_CMP_FIELD& field = m_FieldsBuf[fieldNdx]; if( showCheckBox->GetValue() ) field.m_Attributs &= ~TEXT_NO_VISIBLE; else field.m_Attributs |= TEXT_NO_VISIBLE; if( rotateCheckBox->GetValue() ) field.m_Orient = TEXT_ORIENT_VERT; else field.m_Orient = TEXT_ORIENT_HORIZ; rotateCheckBox->SetValue( field.m_Orient == TEXT_ORIENT_VERT ); field.m_Name = fieldNameTextCtrl->GetValue(); /* Void fields texts for REFERENCE and VALUE (value is the name of the compinent in lib ! ) are not allowed * change them only for a new non void value * When woid, usually netlists are broken */ if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE ) field.m_Text = fieldValueTextCtrl->GetValue(); setRowItem( fieldNdx, field ); // update fieldListCtrl field.m_Size.x = WinEDA_GraphicTextCtrl::ParseSize( textSizeTextCtrl->GetValue(), EESCHEMA_INTERNAL_UNIT, g_UnitMetric ); field.m_Size.y = field.m_Size.x; int style = m_StyleRadioBox->GetSelection(); if( (style & 1 ) != 0 ) field.m_Italic = true; else field.m_Italic = false; if( (style & 2 ) != 0 ) field.m_Bold = true; else field.m_Bold = false; double value; posXTextCtrl->GetValue().ToDouble( &value ); field.m_Pos.x = From_User_Unit( g_UnitMetric, value, EESCHEMA_INTERNAL_UNIT ); posYTextCtrl->GetValue().ToDouble( &value ); field.m_Pos.y = From_User_Unit( g_UnitMetric, value, EESCHEMA_INTERNAL_UNIT ); return true; } void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel() { int choiceCount = unitChoice->GetCount(); // Remove non existing choices (choiceCount must be <= number for parts) int unitcount = m_LibEntry ? m_LibEntry->GetPartCount() : 1; if( unitcount < 1 ) unitcount = 1; if( unitcount < choiceCount ) { while( unitcount < choiceCount ) { choiceCount--; unitChoice->Delete( choiceCount ); } } // For components with multiple parts per package, set the unit selection choiceCount = unitChoice->GetCount(); if( m_Cmp->m_Multi <= choiceCount ) unitChoice->SetSelection( m_Cmp->m_Multi - 1 ); // Disable unit selection if only one unit exists: if( choiceCount <= 1 ) unitChoice->Enable( false ); int orientation = m_Cmp->GetRotationMiroir() & ~(CMP_MIROIR_X | CMP_MIROIR_Y); if( orientation == CMP_ORIENT_90 ) orientationRadioBox->SetSelection( 1 ); else if( orientation == CMP_ORIENT_180 ) orientationRadioBox->SetSelection( 2 ); else if( orientation == CMP_ORIENT_270 ) orientationRadioBox->SetSelection( 3 ); else orientationRadioBox->SetSelection( 0 ); int mirror = m_Cmp->GetRotationMiroir() & (CMP_MIROIR_X | CMP_MIROIR_Y); if( mirror == CMP_MIROIR_X ) { mirrorRadioBox->SetSelection( 1 ); D( printf( "mirror=X,1\n" ); ) } else if( mirror == CMP_MIROIR_Y ) { mirrorRadioBox->SetSelection( 2 ); D( printf( "mirror=Y,2\n" ); ) } else mirrorRadioBox->SetSelection( 0 ); // Activate/Desactivate the normal/convert option ? (activated only if the component has more than one shape) if( m_Cmp->m_Convert > 1 ) { convertCheckBox->SetValue( true ); } if( m_LibEntry == NULL || !m_LibEntry->HasConversion() ) { convertCheckBox->Enable( false ); } // Show the "Parts Locked" option? if( !m_LibEntry || !m_LibEntry->m_UnitSelectionLocked ) { D( printf( "partsAreLocked->false\n" ); ) partsAreLockedLabel->Show( false ); } // Positionnement de la reference en librairie chipnameTextCtrl->SetValue( m_Cmp->m_ChipName ); } /*****************************************************************************/ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event ) /*****************************************************************************/ /* reinitialise components parametres to default values found in lib */ { LIB_COMPONENT* entry; if( m_Cmp == NULL ) return; entry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName ); if( entry == NULL ) return; wxClientDC dc( m_Parent->DrawPanel ); m_Parent->DrawPanel->PrepareGraphicContext( &dc ); RedrawOneStruct( m_Parent->DrawPanel, &dc, m_Cmp, g_XorMode ); /* Initialise fields values to default values found in library: */ LIB_FIELD& refField = entry->GetReferenceField(); m_Cmp->GetField( REFERENCE )->m_Pos = refField.m_Pos + m_Cmp->m_Pos; m_Cmp->GetField( REFERENCE )->ImportValues( refField ); LIB_FIELD& valField = entry->GetValueField(); m_Cmp->GetField( VALUE )->m_Pos = valField.m_Pos + m_Cmp->m_Pos; m_Cmp->GetField( VALUE )->ImportValues( valField ); m_Cmp->SetRotationMiroir( CMP_NORMAL ); m_Parent->GetScreen()->SetModify(); RedrawOneStruct( m_Parent->DrawPanel, &dc, m_Cmp, GR_DEFAULT_DRAWMODE ); EndModal( 1 ); }