#include #include #include "fctsys.h" #include "appl_wxstruct.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::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->SetOrientation( CMP_ORIENT_0 ); break; case 1: m_Cmp->SetOrientation( CMP_ORIENT_90 ); break; case 2: m_Cmp->SetOrientation( CMP_ORIENT_180 ); break; case 3: m_Cmp->SetOrientation( CMP_ORIENT_270 ); break; } int mirror = mirrorRadioBox->GetSelection(); switch( mirror ) { case 0: break; case 1: m_Cmp->SetOrientation( CMP_MIRROR_X ); break; case 2: m_Cmp->SetOrientation( CMP_MIRROR_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 or no value before we copy all of m_FieldsBuf // back into the component for( unsigned i = MANDATORY_FIELDS; im_ChipName ); if( entry && entry->isPower() ) 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 ); // Reference has a specific initialisation, depending on the current active sheet // because for a given component, in a complexe hierarchy, there are more than one // reference. m_Cmp->SetRef( m_Parent->GetSheet(), m_FieldsBuf[REFERENCE].m_Text ); m_Parent->OnModify( ); 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_FIELD blank( wxPoint(), fieldNdx, m_Cmp ); blank.m_Orient = m_FieldsBuf[REFERENCE].m_Orient; m_FieldsBuf.push_back( blank ); m_FieldsBuf[fieldNdx].m_Name = TEMPLATE_FIELDNAME::GetDefaultFieldName(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 < MANDATORY_FIELDS ) { wxBell(); return; } m_skipCopyFromPanel = true; m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx ); fieldListCtrl->DeleteItem( fieldNdx ); if( fieldNdx >= m_FieldsBuf.size() ) --fieldNdx; 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 <= MANDATORY_FIELDS ) { wxBell(); return; } if( !copyPanelToSelectedField() ) return; // swap the fieldNdx field with the one before it, in both the vector // and in the fieldListCtrl SCH_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 ); 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; } SCH_FIELD* DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::findField( const wxString& aFieldName ) { for( unsigned i=0; im_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 // When this code was written, all field constructors ensure that the fixed fields // are all present within a component. So we can knowingly copy them over // in the normal order. Copy only the fixed fields at first. // Please do not break the field constructors. m_FieldsBuf.clear(); for( int i=0; im_Fields[i] ); // make the editable field position relative to the component m_FieldsBuf[i].m_Pos -= m_Cmp->m_Pos; } // Add template fieldnames: // Now copy in the template fields, in the order that they are present in the // template field editor UI. const TEMPLATE_FIELDNAMES& tfnames = m_Parent->GetTemplateFieldNames(); for( TEMPLATE_FIELDNAMES::const_iterator it = tfnames.begin(); it!=tfnames.end(); ++it ) { // add a new field unconditionally to the UI only SCH_FIELD fld( wxPoint(0,0), -1 /* id is a relic */, NULL, it->m_Name ); // See if field by same name already exists in component. SCH_FIELD* schField = aComponent->FindField( it->m_Name ); // If the field does not already exist in the component, then we // use defaults from the template fieldname, otherwise the original // values from the component will be set. if( !schField ) { if( !it->m_Visible ) fld.m_Attributs |= TEXT_NO_VISIBLE; else fld.m_Attributs &= ~TEXT_NO_VISIBLE; fld.m_Text = it->m_Value; // empty? ok too. } else { fld = *schField; // make the editable field position relative to the component fld.m_Pos -= m_Cmp->m_Pos; } m_FieldsBuf.push_back( fld ); } // Lastly, append any original fields from the component which were not added // from the set of fixed fields nor from the set of template fields. for( unsigned i=MANDATORY_FIELDS; im_Fields.size(); ++i ) { SCH_FIELD* cmp = &aComponent->m_Fields[i]; SCH_FIELD* buf = findField( cmp->m_Name ); if( !buf ) { int newNdx = m_FieldsBuf.size(); m_FieldsBuf.push_back( *cmp ); // make the editable field position relative to the component m_FieldsBuf[newNdx].m_Pos -= m_Cmp->m_Pos; } } #if 0 && defined(DEBUG) for( unsigned i = 0; iGetRef( m_Parent->GetSheet() ); 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_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_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 ); // the names of the fixed fields are not editable, others are. fieldNameTextCtrl->Enable( fieldNdx >= MANDATORY_FIELDS ); fieldNameTextCtrl->SetEditable( fieldNdx >= MANDATORY_FIELDS ); // only user defined fields may be moved, and not the top most user defined // field since it would be moving up into the fixed fields, > not >= moveUpButton->Enable( fieldNdx > MANDATORY_FIELDS ); // may only delete user defined fields deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS ); 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->isPower() ) 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 - MANDATORY_FIELDS + 1 ) * 100; coord.y = m_FieldsBuf[REFERENCE].m_Pos.y + ( fieldNdx - MANDATORY_FIELDS + 1 ) * 100; // coord can compute negative if field is < MANDATORY_FIELDS, 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_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->GetOrientation() & ~( CMP_MIRROR_X | CMP_MIRROR_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->GetOrientation() & ( CMP_MIRROR_X | CMP_MIRROR_Y ); if( mirror == CMP_MIRROR_X ) { mirrorRadioBox->SetSelection( 1 ); D( printf( "mirror=X,1\n" ); ) } else if( mirror == CMP_MIRROR_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->UnitsLocked() ) { D( printf( "partsAreLocked->false\n" ); ) partsAreLockedLabel->Show( false ); } // Positionnement de la reference en librairie chipnameTextCtrl->SetValue( m_Cmp->m_ChipName ); } #include "kicad_device_context.h" /* reinitialise components parametres to default values found in lib */ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event ) { LIB_COMPONENT* entry; if( m_Cmp == NULL ) return; entry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName ); if( entry == NULL ) return; INSTALL_DC( dc, m_Parent->DrawPanel ); 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->SetOrientation( CMP_NORMAL ); m_Parent->OnModify( ); RedrawOneStruct( m_Parent->DrawPanel, &dc, m_Cmp, GR_DEFAULT_DRAWMODE ); EndModal( 1 ); }