示例#1
0
文件: schedit.cpp 项目: jerkey/kicad
static void abortMoveItem( EDA_DRAW_PANEL* aPanel, wxDC* aDC )
{
    SCH_SCREEN*     screen = (SCH_SCREEN*) aPanel->GetScreen();
    SCH_ITEM*       item = screen->GetCurItem();
    SCH_EDIT_FRAME* parent = ( SCH_EDIT_FRAME* ) aPanel->GetParent();

    parent->SetRepeatItem( NULL );
    screen->SetCurItem( NULL );

    if( item == NULL )  /* no current item */
        return;

    if( item->IsNew() )
    {
        delete item;
        item = NULL;
    }
    else
    {
        SCH_ITEM* oldItem = parent->GetUndoItem();

        SCH_ITEM* currentItem;

        // Items that are children of other objects are undone by swapping the contents
        // of the parent items.
        if( (item->Type() == SCH_SHEET_PIN_T) || (item->Type() == SCH_FIELD_T) )
        {
            currentItem = (SCH_ITEM*) item->GetParent();
        }
        else
        {
            currentItem = item;
        }

        wxCHECK_RET( oldItem != NULL && currentItem->Type() == oldItem->Type(),
                     wxT( "Cannot restore undefined or bad last schematic item." ) );

        // Never delete existing item, because it can be referenced by an undo/redo command
        // Just restore its data
        currentItem->SwapData( oldItem );

        // Erase the wire representation before the 'normal' view is drawn.
        if ( item->IsWireImage() )
            item->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode );

        item->ClearFlags();
    }

    aPanel->Refresh();
}
示例#2
0
SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                             int aHotKeyCommandId,
                                             bool* aClarificationMenuCancelled )
{
    SCH_ITEM*      item;
    LIB_PIN*       Pin     = NULL;
    SCH_COMPONENT* component = NULL;
    wxPoint        gridPosition = GetNearestGridPosition( aPosition );

    // Check the on grid position first.  There is more likely to be multiple items on
    // grid than off grid.
    m_canvas->SetAbortRequest( false ); // be sure a old abort request in not pending
    item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );

    // If the user aborted the clarification context menu, don't show it again at the
    // off grid position.
    if( !item && m_canvas->GetAbortRequest() )
    {
        if( aClarificationMenuCancelled )
            *aClarificationMenuCancelled = true;

        m_canvas->SetAbortRequest( false );
        return NULL;
    }

    if( !item && (aPosition != gridPosition) )
        item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );

    if( !item )
    {
        if( aClarificationMenuCancelled )
            *aClarificationMenuCancelled = m_canvas->GetAbortRequest();

        m_canvas->SetAbortRequest( false );  // Just in case the user aborted the context menu.
        return NULL;
    }

    // Cross probing to Pcbnew if a pin or a component is found
    switch( item->Type() )
    {
    case SCH_FIELD_T:
    case LIB_FIELD_T:
        component = (SCH_COMPONENT*) item->GetParent();
        SendMessageToPCBNEW( item, component );
        break;

    case SCH_COMPONENT_T:
        component = (SCH_COMPONENT*) item;
        SendMessageToPCBNEW( item, component );
        break;

    case LIB_PIN_T:
        Pin = (LIB_PIN*) item;
        component = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
        break;

    /* case SCH_SHEET_T: */
    /*     // This may lag on larger projects */
    /*     SendMessageToPCBNEW( item, nullptr ); */
    /*     break; */
    default:
        ;
    }

    if( Pin )
    {
        // Force display pin information (the previous display could be a component info)
        MSG_PANEL_ITEMS items;

        Pin->GetMsgPanelInfo( m_UserUnits, items, component );

        SetMsgPanel( items );

        // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
        SendMessageToPCBNEW( Pin, component );
    }

    return item;
}
示例#3
0
SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                      int aHotKeyCommandId )
{
    SCH_ITEM* item = NULL;

    m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );

    if( m_collectedItems.GetCount() == 0 )
    {
        ClearMsgPanel();
    }
    else if( m_collectedItems.GetCount() == 1 )
    {
        item = m_collectedItems[0];
    }
    else
    {
        // There are certain parent/child and enclosure combinations that can be handled
        // automatically.  Since schematics are meant to be human-readable we don't have
        // all the various overlap and coverage issues that we do in Pcbnew.
        if( m_collectedItems.GetCount() == 2 )
        {
            SCH_ITEM* a = m_collectedItems[ 0 ];
            SCH_ITEM* b = m_collectedItems[ 1 ];

            if( a->GetParent() == b )
                item = a;
            else if( a == b->GetParent() )
                item = b;
            else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
                item = b;
            else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
                item = a;
        }

        // There are certain combinations of items that do not need clarification such as
        // a corner were two lines meet or all the items form a junction.
        if( aHotKeyCommandId )
        {
            switch( aHotKeyCommandId )
            {
            case HK_DRAG:
                if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
                    || m_collectedItems.IsDraggableJunction() )
                {
                    item = m_collectedItems[0];
                }
                break;

            case HK_MOVE_COMPONENT_OR_ITEM:
                if( m_collectedItems.GetCount() == 2 &&
                        dynamic_cast< SCH_SHEET_PIN * >( m_collectedItems[0] ) &&
                        dynamic_cast< SCH_SHEET * >( m_collectedItems[1] ) )
                {
                    item = m_collectedItems[0];
                }
                break;

            default:
                ;
            }
        }

        if( item == NULL )
        {
            wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
                          wxT( "Select item clarification context menu size limit exceeded." ) );

            wxMenu selectMenu;

            AddMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ), KiBitmap( info_xpm ) );
            selectMenu.AppendSeparator();

            for( int i = 0;  i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS;  i++ )
            {
                wxString text = m_collectedItems[i]->GetSelectMenuText( m_UserUnits );
                BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
                AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
            }

            // Set to NULL in case the user aborts the clarification context menu.
            GetScreen()->SetCurItem( NULL );
            m_canvas->SetAbortRequest( true );   // Changed to false if an item is selected
            PopupMenu( &selectMenu );

            if( !m_canvas->GetAbortRequest() )
            {
                m_canvas->MoveCursorToCrossHair();
                item = GetScreen()->GetCurItem();
            }
        }
    }

    GetScreen()->SetCurItem( item );

    if( item )
    {
        if( item->Type() == SCH_COMPONENT_T )
            ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );

        MSG_PANEL_ITEMS items;
        item->GetMsgPanelInfo( m_UserUnits, items );
        SetMsgPanel( items );
    }
    else
    {
        ClearMsgPanel();
    }

    return item;
}
SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
                                             int aHotKeyCommandId )
{
    SCH_ITEM*      item;
    wxString       msg;
    LIB_PIN*       Pin     = NULL;
    SCH_COMPONENT* LibItem = NULL;
    wxPoint        gridPosition = GetNearestGridPosition( aPosition );

    // Check the on grid position first.  There is more likely to be multiple items on
    // grid than off grid.
    item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );

    // If the user aborted the clarification context menu, don't show it again at the
    // off grid position.
    if( !item && m_canvas->GetAbortRequest() )
    {
        m_canvas->SetAbortRequest( false );
        return NULL;
    }

    if( !item && (aPosition != gridPosition) )
        item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );

    if( !item )
    {
        m_canvas->SetAbortRequest( false );  // Just in case the user aborted the context menu.
        return NULL;
    }

    // Cross probing to Pcbnew if a pin or a component is found
    switch( item->Type() )
    {
    case SCH_FIELD_T:
    case LIB_FIELD_T:
        LibItem = (SCH_COMPONENT*) item->GetParent();
        SendMessageToPCBNEW( item, LibItem );
        break;

    case SCH_COMPONENT_T:
        LibItem = (SCH_COMPONENT*) item;
        SendMessageToPCBNEW( item, LibItem );
        break;

    case LIB_PIN_T:
        Pin = (LIB_PIN*) item;
        LibItem = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
        break;

    default:
        ;
    }

    if( Pin )
    {
        // Force display pin information (the previous display could be a component info)
        MSG_PANEL_ITEMS items;

        Pin->GetMsgPanelInfo( items );

        if( LibItem )
            items.push_back( MSG_PANEL_ITEM( LibItem->GetRef( m_CurrentSheet ),
                                             LibItem->GetField( VALUE )->GetShownText(), DARKCYAN ) );

        SetMsgPanel( items );

        // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
        SendMessageToPCBNEW( Pin, LibItem );
    }

    return item;
}
void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
{
    SCH_ITEM*   item = GetScreen()->GetCurItem();
    wxPoint     gridPosition = GetGridPosition( aPosition );

    if( ( GetToolId() == ID_NO_TOOL_SELECTED ) || ( item && item->GetFlags() ) )
    {
        m_canvas->SetAutoPanRequest( false );
        SetRepeatItem( NULL );

        if( item && item->GetFlags() )
        {
            switch( item->Type() )
            {
            case SCH_LABEL_T:
            case SCH_GLOBAL_LABEL_T:
            case SCH_HIERARCHICAL_LABEL_T:
            case SCH_TEXT_T:
            case SCH_SHEET_PIN_T:
            case SCH_SHEET_T:
            case SCH_BUS_WIRE_ENTRY_T:
            case SCH_BUS_BUS_ENTRY_T:
            case SCH_JUNCTION_T:
            case SCH_COMPONENT_T:
            case SCH_FIELD_T:
            case SCH_BITMAP_T:
            case SCH_NO_CONNECT_T:
                addCurrentItemToList();
                return;

            case SCH_LINE_T:    // May already be drawing segment.
                break;

            default:
                wxFAIL_MSG( wxT( "SCH_EDIT_FRAME::OnLeftClick error.  Item type <" ) +
                            item->GetClass() + wxT( "> is already being edited." ) );
                item->ClearFlags();
                break;
            }
        }
        else
        {
            item = LocateAndShowItem( aPosition );
        }
    }

    switch( GetToolId() )
    {
    case ID_NO_TOOL_SELECTED:
        break;

    case ID_HIGHLIGHT:
        HighlightConnectionAtPosition( aPosition );
        break;

    case ID_HIERARCHY_PUSH_POP_BUTT:
        if( ( item && item->GetFlags() ) || ( g_RootSheet->CountSheets() == 0 ) )
            break;

        item = LocateAndShowItem( aPosition, SCH_COLLECTOR::SheetsOnly );

        if( item )  // The user has clicked on a sheet: this is an enter sheet command
        {
            m_CurrentSheet->push_back( (SCH_SHEET*) item );
            DisplayCurrentSheet();
        }
        else if( m_CurrentSheet->Last() != g_RootSheet )
        {   // The user has clicked ouside a sheet:this is an leave sheet command
            m_CurrentSheet->pop_back();
            DisplayCurrentSheet();
        }
        break;

    case ID_NOCONN_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            if( GetScreen()->GetItem( gridPosition, 0, SCH_NO_CONNECT_T ) == NULL )
            {
                SCH_NO_CONNECT*  no_connect = AddNoConnect( aDC, gridPosition );
                SetRepeatItem( no_connect );
                GetScreen()->SetCurItem( no_connect );
                m_canvas->SetAutoPanRequest( true );
            }
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_JUNCTION_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            if( GetScreen()->GetItem( gridPosition, 0, SCH_JUNCTION_T ) == NULL )
            {
                SCH_JUNCTION* junction = AddJunction( aDC, gridPosition, true );
                SetRepeatItem( junction );
                GetScreen()->SetCurItem( junction );
                m_canvas->SetAutoPanRequest( true );
            }
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_WIRETOBUS_ENTRY_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            CreateBusWireEntry();
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_BUSTOBUS_ENTRY_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            CreateBusBusEntry();
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_SCHEMATIC_DELETE_ITEM_BUTT:
        DeleteItemAtCrossHair( aDC );
        break;

    case ID_WIRE_BUTT:
        BeginSegment( aDC, LAYER_WIRE );
        m_canvas->SetAutoPanRequest( true );
        break;

    case ID_BUS_BUTT:
        BeginSegment( aDC, LAYER_BUS );
        m_canvas->SetAutoPanRequest( true );
        break;

    case ID_LINE_COMMENT_BUTT:
        BeginSegment( aDC, LAYER_NOTES );
        m_canvas->SetAutoPanRequest( true );
        break;

    case ID_TEXT_COMMENT_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            GetScreen()->SetCurItem( CreateNewText( aDC, LAYER_NOTES ) );
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_ADD_IMAGE_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            GetScreen()->SetCurItem( CreateNewImage( aDC ) );
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_LABEL_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            GetScreen()->SetCurItem( CreateNewText( aDC, LAYER_LOCLABEL ) );
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_GLABEL_BUTT:
    case ID_HIERLABEL_BUTT:
        if( (item == NULL) || (item->GetFlags() == 0) )
        {
            if( GetToolId() == ID_GLABEL_BUTT )
                GetScreen()->SetCurItem( CreateNewText( aDC, LAYER_GLOBLABEL ) );

            if( GetToolId() == ID_HIERLABEL_BUTT )
                GetScreen()->SetCurItem( CreateNewText( aDC, LAYER_HIERLABEL ) );

            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_SHEET_SYMBOL_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            item = CreateSheet( aDC );

            if( item != NULL )
            {
                GetScreen()->SetCurItem( item );
                m_canvas->SetAutoPanRequest( true );
            }
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_IMPORT_HLABEL_BUTT:
    case ID_SHEET_PIN_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
            item = LocateAndShowItem( aPosition, SCH_COLLECTOR::SheetsAndSheetLabels );

        if( item == NULL )
            break;

        if( (item->Type() == SCH_SHEET_T) && (item->GetFlags() == 0) )
        {
            if( GetToolId() == ID_IMPORT_HLABEL_BUTT )
                GetScreen()->SetCurItem( ImportSheetPin( (SCH_SHEET*) item, aDC ) );
            else
                GetScreen()->SetCurItem( CreateSheetPin( (SCH_SHEET*) item, aDC ) );
        }
        else if( (item->Type() == SCH_SHEET_PIN_T) && (item->GetFlags() != 0) )
        {
            addCurrentItemToList();
        }
        break;

    case ID_SCH_PLACE_COMPONENT:
        if( (item == NULL) || (item->GetFlags() == 0) )
        {
            GetScreen()->SetCurItem( Load_Component( aDC, NULL,
                                                     s_CmpNameList, s_CmpLastUnit, true ) );
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

    case ID_PLACE_POWER_BUTT:
        if( ( item == NULL ) || ( item->GetFlags() == 0 ) )
        {
            SCHLIB_FILTER filter;
            filter.FilterPowerParts( true );
            GetScreen()->SetCurItem( Load_Component( aDC, &filter,
                                                     s_PowerNameList, s_LastPowerUnit, false ) );
            m_canvas->SetAutoPanRequest( true );
        }
        else
        {
            addCurrentItemToList();
        }
        break;

#ifdef KICAD_SPICE
    case ID_SIM_PROBE:
        {
            const KICAD_T wiresAndComponents[] = { SCH_LINE_T, SCH_COMPONENT_T, SCH_SHEET_PIN_T };
            item = LocateAndShowItem( aPosition, wiresAndComponents );

            if( !item )
                break;

            NETLIST_OBJECT_LIST* netlist = BuildNetListBase();

            for( NETLIST_OBJECT* obj : *netlist )
            {
                if( obj->m_Comp == item )
                {
                    SIM_PLOT_FRAME* simFrame = (SIM_PLOT_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );

                    if( simFrame )
                        simFrame->AddVoltagePlot( obj->GetNetName() );

                    break;
                }
            }
        }
        break;

    case ID_SIM_TUNE:
        {
            const KICAD_T fieldsAndComponents[] = { SCH_COMPONENT_T, SCH_FIELD_T };
            item = LocateAndShowItem( aPosition, fieldsAndComponents );

            if( !item )
                return;

            if( item->Type() != SCH_COMPONENT_T )
            {
                item = static_cast<SCH_ITEM*>( item->GetParent() );

                if( item->Type() != SCH_COMPONENT_T )
                    return;
            }

            SIM_PLOT_FRAME* simFrame = (SIM_PLOT_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );

            if( simFrame )
                simFrame->AddTuner( static_cast<SCH_COMPONENT*>( item ) );
        }
        break;
#endif /* KICAD_SPICE */

    default:
        SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString );
        wxFAIL_MSG( wxT( "SCH_EDIT_FRAME::OnLeftClick invalid tool ID <" ) +
                    wxString::Format( wxT( "%d> selected." ), GetToolId() ) );
    }
}
示例#6
0
void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent )
{
    SCH_SCREEN* screen = GetScreen();
    SCH_ITEM*   item = screen->GetCurItem();

    INSTALL_UNBUFFERED_DC( dc, m_canvas );

    // Allows block rotate operation on hot key.
    if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
    {
        screen->m_BlockLocate.SetCommand( BLOCK_ROTATE );
        HandleBlockEnd( &dc );
        return;
    }

    if( item == NULL )
    {
        // If we didn't get here by a hot key, then something has gone wrong.
        if( aEvent.GetInt() == 0 )
            return;

        EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject();

        wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );

        item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::RotatableItems,
                                  aEvent.GetInt() );

        // Exit if no item found at the current location or the item is already being edited.
        if( (item == NULL) || (item->GetFlags() != 0) )
            return;
    }

    switch( item->Type() )
    {
    case SCH_COMPONENT_T:
        {
            SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
            if( aEvent.GetId() == ID_SCH_ROTATE_CLOCKWISE )
                OrientComponent( CMP_ROTATE_CLOCKWISE );
            else if( aEvent.GetId() == ID_SCH_ROTATE_COUNTERCLOCKWISE )
                OrientComponent( CMP_ROTATE_COUNTERCLOCKWISE );
            else
                wxFAIL_MSG( wxT( "Unknown rotate item command ID." ) );

            if( m_autoplaceFields )
                component->AutoAutoplaceFields( GetScreen() );

            m_canvas->Refresh();

            break;
        }

    case SCH_TEXT_T:
    case SCH_LABEL_T:
    case SCH_GLOBAL_LABEL_T:
    case SCH_HIERARCHICAL_LABEL_T:
        m_canvas->MoveCursorToCrossHair();
        ChangeTextOrient( (SCH_TEXT*) item );
        m_canvas->Refresh();
        break;

    case SCH_FIELD_T:
        m_canvas->MoveCursorToCrossHair();
        RotateField( (SCH_FIELD*) item );
        if( item->GetParent()->Type() == SCH_COMPONENT_T )
        {
            // Now that we're moving a field, they're no longer autoplaced.
            SCH_COMPONENT *parent = static_cast<SCH_COMPONENT*>( item->GetParent() );
            parent->ClearFieldsAutoplaced();
        }
        m_canvas->Refresh();
        break;

    case SCH_BITMAP_T:
        RotateImage( (SCH_BITMAP*) item );
        break;

    case SCH_SHEET_T:
        if( !item->IsNew() )    // rotate a sheet during its creation has no sense
        {
            bool retCCW = ( aEvent.GetId() == ID_SCH_ROTATE_COUNTERCLOCKWISE );
            RotateHierarchicalSheet( static_cast<SCH_SHEET*>( item ), retCCW );
        }

        break;

    case SCH_JUNCTION_T:
    case SCH_NO_CONNECT_T:
        // these items are not rotated, because rotation does not change them.
        break;

    default:
        // Other items (wires...) cannot be rotated, at least during creation
        if( item->IsNew() )
            break;

        wxFAIL_MSG( wxString::Format( wxT( "Cannot rotate schematic item type %s." ),
                                      GetChars( item->GetClass() ) ) );
    }

    if( item->GetFlags() == 0 )
        screen->SetCurItem( NULL );
}
示例#7
0
void SCH_EDIT_FRAME::addCurrentItemToList( wxDC* aDC )
{
    SCH_SCREEN* screen = GetScreen();
    SCH_ITEM*   item = screen->GetCurItem();

    wxCHECK_RET( item != NULL, wxT( "Cannot add current item to list." ) );

    m_canvas->SetAutoPanRequest( false );

    SCH_ITEM* undoItem = item;

    if( item->Type() == SCH_SHEET_PIN_T )
    {
        SCH_SHEET* sheet = (SCH_SHEET*) item->GetParent();

        wxCHECK_RET( (sheet != NULL) && (sheet->Type() == SCH_SHEET_T),
                     wxT( "Cannot place sheet pin in invalid schematic sheet object." ) );

        undoItem = sheet;
    }

    else if( item->Type() == SCH_FIELD_T )
    {
        SCH_COMPONENT* cmp = (SCH_COMPONENT*) item->GetParent();

        wxCHECK_RET( (cmp != NULL) && (cmp->Type() == SCH_COMPONENT_T),
                     wxT( "Cannot place field in invalid schematic component object." ) );

        undoItem = cmp;
    }

    if( item->IsNew() )
    {
        if( item->Type() == SCH_SHEET_T )
        {
            // Fix the size and position of the new sheet using the last values set by
            // the m_mouseCaptureCallback function.
            m_canvas->SetMouseCapture( NULL, NULL );

            if( !EditSheet( (SCH_SHEET*)item, aDC ) )
            {
                screen->SetCurItem( NULL );
                item->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode );
                delete item;
                return;
            }

            SetSheetNumberAndCount();
        }

        if( undoItem == item )
        {
            if( !screen->CheckIfOnDrawList( item ) )  // don't want a loop!
                screen->Append( item );

            SetRepeatItem( item );

            SaveCopyInUndoList( undoItem, UR_NEW );
        }
        else
        {
            // Here, item is not a basic schematic item, but an item inside
            // a parent basic schematic item,
            // currently: sheet pin or component field.
            // currently, only a sheet pin can be found as new item,
            // because new component fields have a specific handling, and do not appears here
            SaveCopyInUndoList( undoItem, UR_CHANGED );

            if( item->Type() == SCH_SHEET_PIN_T )
                ( (SCH_SHEET*)undoItem )->AddPin( (SCH_SHEET_PIN*) item );
            else
                wxLogMessage(wxT( "addCurrentItemToList: expected type = SCH_SHEET_PIN_T, actual type = %d" ),
                            item->Type() );
        }
    }
    else
    {
        SaveUndoItemInUndoList( undoItem );
    }

    // Erase the wire representation before the 'normal' view is drawn.
    if ( item->IsWireImage() )
        item->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode );

    item->ClearFlags();
    screen->SetModify();
    screen->SetCurItem( NULL );
    m_canvas->SetMouseCapture( NULL, NULL );
    m_canvas->EndMouseCapture();

    if( item->IsConnectable() )
        screen->TestDanglingEnds();

    if( aDC )
    {
        EDA_CROSS_HAIR_MANAGER( m_canvas, aDC );  // Erase schematic cursor
        undoItem->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
    }
}