TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) :
    BOARD_ITEM( parent, PCB_MODULE_TEXT_T ),
    EDA_TEXT()
{
    MODULE* module = static_cast<MODULE*>( m_Parent );

    m_Type = text_type;
    m_unlocked = false;

    // Set text thickness to a default value
    SetThickness( Millimeter2iu( 0.15 ) );
    SetLayer( F_SilkS );

    // Set position and give a default layer if a valid parent footprint exists
    if( module && ( module->Type() == PCB_MODULE_T ) )
    {
        SetTextPos( module->GetPosition() );

        if( IsBackLayer( module->GetLayer() ) )
        {
            SetLayer( B_SilkS );
            SetMirrored( true );
        }
    }

    SetDrawCoord();
}
TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) :
    BOARD_ITEM( parent, PCB_MODULE_TEXT_T ),
    EDA_TEXT()
{
    MODULE* module = (MODULE*) m_Parent;

    m_Type = text_type;

    m_NoShow = false;

    // Set text tickness to a default value
    m_Thickness = Millimeter2iu( 0.15 );

    SetLayer( SILKSCREEN_N_FRONT );

    if( module && ( module->Type() == PCB_MODULE_T ) )
    {
        m_Pos = module->GetPosition();

        if( IsBackLayer( module->GetLayer() ) )
        {
            SetLayer( SILKSCREEN_N_BACK );
            m_Mirror = true;
        }
        else
        {
            SetLayer( SILKSCREEN_N_FRONT );
            m_Mirror = false;
        }
    }
}
Exemplo n.º 3
0
void TEXTE_MODULE::Flip( const wxPoint& aCentre )
{
    // flipping the footprint is relative to the X axis
    MIRROR( m_Pos.y, aCentre.y );
    NEGATE_AND_NORMALIZE_ANGLE_POS( m_Orient );
    SetLayer( FlipLayer( GetLayer() ) );
    m_Mirror = IsBackLayer( GetLayer() );
    SetLocalCoord();
}
void PCB_DRAW_PANEL_GAL::SetTopLayer( LAYER_ID aLayer )
{
    m_view->ClearTopLayers();
    setDefaultLayerOrder();
    m_view->SetTopLayer( aLayer );

    // Layers that should always have on-top attribute enabled
    const LAYER_NUM layers[] = {
            ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ),
            ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ),
            ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ),
            ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( RATSNEST_VISIBLE ), Dwgs_User,
            ITEM_GAL_LAYER( DRC_VISIBLE )
    };

    for( unsigned int i = 0; i < sizeof( layers ) / sizeof( LAYER_NUM ); ++i )
        m_view->SetTopLayer( layers[i] );

    // Extra layers that are brought to the top if a F.* or B.* is selected
    const LAYER_NUM frontLayers[] = {
        F_Cu, F_Adhes, F_Paste, F_SilkS, F_Mask, F_CrtYd, F_Fab, ITEM_GAL_LAYER( PAD_FR_VISIBLE ),
        NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ), NETNAMES_GAL_LAYER( F_Cu ), -1
    };

    const LAYER_NUM backLayers[] = {
        B_Cu, B_Adhes, B_Paste, B_SilkS, B_Mask, B_CrtYd, B_Fab, ITEM_GAL_LAYER( PAD_BK_VISIBLE ),
        NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ), NETNAMES_GAL_LAYER( B_Cu ), -1
    };

    const LAYER_NUM* extraLayers = NULL;

    // Bring a few more extra layers to the top depending on the selected board side
    if( IsFrontLayer( aLayer ) )
        extraLayers = frontLayers;
    else if( IsBackLayer( aLayer ) )
        extraLayers = backLayers;

    if( extraLayers )
    {
        const LAYER_NUM* l = extraLayers;

        while( *l >= 0 )
            m_view->SetTopLayer( *l++ );

        // Move the active layer to the top
        if( !IsCopperLayer( aLayer ) )
            m_view->SetLayerOrder( aLayer, m_view->GetLayerOrder( GAL_LAYER_ORDER[0] ) );
    }
    else if( IsCopperLayer( aLayer ) )
    {
        // Display labels for copper layers on the top
        m_view->SetTopLayer( GetNetnameLayer( aLayer ) );
    }

    m_view->UpdateAllLayersOrder();
}
void TEXTE_MODULE::Flip( const wxPoint& aCentre )
{
    // flipping the footprint is relative to the X axis
    SetTextY( ::Mirror( GetTextPos().y, aCentre.y ) );

    SetTextAngle( -GetTextAngle() );

    SetLayer( FlipLayer( GetLayer() ) );
    SetMirrored( IsBackLayer( GetLayer() ) );
    SetLocalCoord();
}
Exemplo n.º 6
0
unsigned int D_PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
{
    if( aView->GetPrintMode() > 0 )  // In printing mode the pad is always drawable
        return 0;

    const int HIDE = std::numeric_limits<unsigned int>::max();
    BOARD* board = GetBoard();

    // Handle Render tab switches
    if( ( GetAttribute() == PAD_ATTRIB_STANDARD || GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
         && !aView->IsLayerVisible( LAYER_PADS_TH ) )
        return HIDE;

    if( !IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
        return HIDE;

    if( IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
        return HIDE;

    if( IsFrontLayer( ( PCB_LAYER_ID )aLayer ) && !aView->IsLayerVisible( LAYER_PAD_FR ) )
        return HIDE;

    if( IsBackLayer( ( PCB_LAYER_ID )aLayer ) && !aView->IsLayerVisible( LAYER_PAD_BK ) )
        return HIDE;

    // Only draw the pad if at least one of the layers it crosses is being displayed
    if( board && !( board->GetVisibleLayers() & GetLayerSet() ).any() )
        return HIDE;

    // Netnames will be shown only if zoom is appropriate
    if( IsNetnameLayer( aLayer ) )
    {
        int divisor = std::max( m_Size.x, m_Size.y );

        // Pad sizes can be zero briefly when someone is typing a number like "0.5"
        // in the pad properties dialog
        if( divisor == 0 )
            return HIDE;

        return ( Millimeter2iu( 10 ) / divisor );
    }

    // Other layers are shown without any conditions
    return 0;
}
Exemplo n.º 7
0
unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer ) const
{
    const int MAX = std::numeric_limits<unsigned int>::max();

    if( !m_view )
        return 0;

    if( m_Type == TEXT_is_VALUE && !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_VALUES_VISIBLE ) ) )
        return MAX;

    if( m_Type == TEXT_is_REFERENCE && !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_REFERENCES_VISIBLE ) ) )
        return MAX;

    if( IsFrontLayer( m_Layer ) && ( !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ) ) ||
                                     !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_FR_VISIBLE ) ) ) )
        return MAX;

    if( IsBackLayer( m_Layer ) && ( !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_TEXT_BK_VISIBLE ) ) ||
                                    !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_BK_VISIBLE ) ) ) )
        return MAX;

    return 0;
}
unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
{
    const int HIDE = std::numeric_limits<unsigned int>::max();

    if( !aView )
        return 0;

    // Hidden text gets put on the LAYER_MOD_TEXT_INVISIBLE for rendering, but
    // should only render if its native layer is visible.
    if( !aView->IsLayerVisible( GetLayer() ) )
        return HIDE;

    // Handle Render tab switches
    if( ( m_Type == TEXT_is_VALUE || m_Text == wxT( "%V" ) )
            && !aView->IsLayerVisible( LAYER_MOD_VALUES ) )
        return HIDE;

    if( ( m_Type == TEXT_is_REFERENCE || m_Text == wxT( "%R" ) )
            && !aView->IsLayerVisible( LAYER_MOD_REFERENCES ) )
        return HIDE;

    if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
        return HIDE;

    if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
        return HIDE;

    if( IsFrontLayer( m_Layer ) && !aView->IsLayerVisible( LAYER_MOD_TEXT_FR ) )
        return HIDE;

    if( IsBackLayer( m_Layer ) && !aView->IsLayerVisible( LAYER_MOD_TEXT_BK ) )
        return HIDE;

    // Other layers are shown without any conditions
    return 0;
}
void TEXTE_MODULE::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
                         const wxPoint& aOffset )
{
    if( aPanel == NULL )
        return;

    /* parent must *not* be NULL (a footprint text without a footprint
       parent has no sense) */
    wxASSERT( m_Parent );

    BOARD* brd = GetBoard( );

    auto frame = static_cast<PCB_BASE_FRAME*> ( aPanel->GetParent() );
    auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );

    PCB_LAYER_ID text_layer = GetLayer();

    if( !brd->IsLayerVisible( m_Layer )
      || ( IsFrontLayer( text_layer ) && !brd->IsElementVisible( LAYER_MOD_TEXT_FR ) )
      || ( IsBackLayer( text_layer ) && !brd->IsElementVisible( LAYER_MOD_TEXT_BK ) ) )
        return;

    if( !brd->IsElementVisible( LAYER_MOD_REFERENCES ) && GetText() == wxT( "%R" ) )
        return;

    if( !brd->IsElementVisible( LAYER_MOD_VALUES ) && GetText() == wxT( "%V" ) )
        return;

    // Invisible texts are still drawn (not plotted) in LAYER_MOD_TEXT_INVISIBLE
    // Just because we must have to edit them (at least to make them visible)
    if( !IsVisible() )
    {
        if( !brd->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) )
            return;

        color = frame->Settings().Colors().GetItemColor( LAYER_MOD_TEXT_INVISIBLE );
    }

    auto displ_opts = (PCB_DISPLAY_OPTIONS*)( aPanel->GetDisplayOptions() );

    // shade text if high contrast mode is active
    if( ( aDrawMode & GR_ALLOW_HIGHCONTRAST ) && displ_opts && displ_opts->m_ContrastModeDisplay )
    {
        PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) aPanel->GetScreen() )->m_Active_Layer;

        if( !IsOnLayer( curr_layer ) )
            color = COLOR4D( DARKDARKGRAY );
    }

    // Draw mode compensation for the width
    int width = GetThickness();

    if( displ_opts && displ_opts->m_DisplayModTextFill == SKETCH )
        width = -width;

    GRSetDrawMode( aDC, aDrawMode );
    wxPoint pos = GetTextPos() - aOffset;

    // Draw the text anchor point
    if( brd->IsElementVisible( LAYER_ANCHOR ) )
    {
        COLOR4D anchor_color = frame->Settings().Colors().GetItemColor( LAYER_ANCHOR );
        GRDrawAnchor( aPanel->GetClipBox(), aDC, pos.x, pos.y, DIM_ANCRE_TEXTE, anchor_color );
    }

    // Draw the text proper, with the right attributes
    wxSize size   = GetTextSize();
    double orient = GetDrawRotation();

    // If the text is mirrored : negate size.x (mirror / Y axis)
    if( IsMirrored() )
        size.x = -size.x;

    DrawGraphicText( aPanel->GetClipBox(), aDC, pos, color, GetShownText(), orient,
                     size, GetHorizJustify(), GetVertJustify(),
                     width, IsItalic(), IsBold() );

    // Enable these line to draw the bounding box (debug test purpose only)
#if 0
    {
        EDA_RECT BoundaryBox = GetBoundingBox();
        GRRect( aPanel->GetClipBox(), aDC, BoundaryBox, 0, BROWN );
    }
#endif
}
Exemplo n.º 10
0
void TEXTE_MODULE::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
                         const wxPoint& aOffset )
{
    if( aPanel == NULL )
        return;

    /* parent must *not* be NULL (a footprint text without a footprint
       parent has no sense) */
    wxASSERT( m_Parent );

    BOARD* brd = GetBoard( );
    EDA_COLOR_T color = brd->GetLayerColor( GetLayer() );
    LAYER_ID text_layer = GetLayer();

    if( !brd->IsLayerVisible( m_Layer )
      || (IsFrontLayer( text_layer ) && !brd->IsElementVisible( MOD_TEXT_FR_VISIBLE ))
      || (IsBackLayer( text_layer ) && !brd->IsElementVisible( MOD_TEXT_BK_VISIBLE )) )
        return;

    // Invisible texts are still drawn (not plotted) in MOD_TEXT_INVISIBLE
    // Just because we must have to edit them (at least to make them visible)
    if( m_NoShow )
    {
        if( !brd->IsElementVisible( MOD_TEXT_INVISIBLE ) )
            return;

        color = brd->GetVisibleElementColor( MOD_TEXT_INVISIBLE );
    }

    DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)aPanel->GetDisplayOptions();

    // shade text if high contrast mode is active
    if( ( aDrawMode & GR_ALLOW_HIGHCONTRAST ) && displ_opts && displ_opts->m_ContrastModeDisplay )
    {
        LAYER_ID curr_layer = ( (PCB_SCREEN*) aPanel->GetScreen() )->m_Active_Layer;

        if( !IsOnLayer( curr_layer ) )
            ColorTurnToDarkDarkGray( &color );
    }

    // Draw mode compensation for the width
    int width = m_Thickness;

    if( displ_opts && displ_opts->m_DisplayModTextFill == SKETCH )
        width = -width;

    GRSetDrawMode( aDC, aDrawMode );
    wxPoint pos = m_Pos - aOffset;

    // Draw the text anchor point
    if( brd->IsElementVisible( ANCHOR_VISIBLE ) )
    {
        EDA_COLOR_T anchor_color = brd->GetVisibleElementColor(ANCHOR_VISIBLE);
        GRDrawAnchor( aPanel->GetClipBox(), aDC, pos.x, pos.y, DIM_ANCRE_TEXTE, anchor_color );
    }

    // Draw the text proper, with the right attributes
    wxSize size   = m_Size;
    double orient = GetDrawRotation();

    // If the text is mirrored : negate size.x (mirror / Y axis)
    if( m_Mirror )
        size.x = -size.x;

    DrawGraphicText( aPanel->GetClipBox(), aDC, pos, color, GetShownText(), orient,
                     size, m_HJustify, m_VJustify, width, m_Italic, m_Bold );

    // Enable these line to draw the bounding box (debug test purpose only)
#if 0
    {
        EDA_RECT BoundaryBox = GetBoundingBox();
        GRRect( aPanel->GetClipBox(), aDC, BoundaryBox, 0, BROWN );
    }
#endif
}
bool DialogEditModuleText::TransferDataFromWindow()
{
    if( !Validate() || !DialogEditModuleText_base::TransferDataFromWindow() )
        return false;

    if( m_module )
        m_parent->SaveCopyInUndoList( m_module, UR_CHANGED );

#ifndef USE_WX_OVERLAY
    if( m_dc )     //Erase old text on screen
    {
        m_currentText->Draw( m_parent->GetCanvas(), m_dc, GR_XOR,
                             (m_currentText->IsMoving()) ? MoveVector : wxPoint( 0, 0 ) );
    }
#endif

    m_currentText->SetText( m_Name->GetValue() );
    m_currentText->SetItalic( m_Style->GetSelection() == 1 );

    wxPoint tmp;

    tmp.x = ValueFromString( g_UserUnit, m_TxtPosCtrlX->GetValue() );
    tmp.y = ValueFromString( g_UserUnit, m_TxtPosCtrlY->GetValue() );

    m_currentText->SetPos0( tmp );

    wxSize textSize( wxSize( ValueFromString( g_UserUnit, m_TxtSizeCtrlX->GetValue() ),
                             ValueFromString( g_UserUnit, m_TxtSizeCtrlY->GetValue() ) ) );

    // Test for a reasonable size:
    if( textSize.x < TEXTS_MIN_SIZE )
        textSize.x = TEXTS_MIN_SIZE;

    if( textSize.y < TEXTS_MIN_SIZE )
        textSize.y = TEXTS_MIN_SIZE;

    m_currentText->SetSize( textSize );

    int width = ValueFromString( g_UserUnit, m_TxtWidthCtlr->GetValue() );

    // Test for a reasonable width:
    if( width <= 1 )
        width = 1;

    int maxthickness = Clamp_Text_PenSize(width, m_currentText->GetSize() );

    if( width > maxthickness )
    {
        DisplayError( NULL,
                      _( "The text thickness is too large for the text size. It will be clamped" ) );
        width = maxthickness;
    }

    m_currentText->SetThickness( width );

    m_currentText->SetVisible( m_Show->GetSelection() == 0 );

    bool custom_orientation = false;
    switch( m_Orient->GetSelection() )
    {
    case 0:
        m_currentText->SetOrientation( 0 );
        break;

    case 1:
        m_currentText->SetOrientation( 900 );
        break;

    case 2:
        m_currentText->SetOrientation( -900 );
        break;

    default:
        custom_orientation = true;
        m_currentText->SetOrientation( KiROUND( m_OrientValue * 10.0 ) );
        break;
    };

    switch( int( m_currentText->GetOrientation() ) )
    {
    case 0:
        m_Orient->SetSelection( 0 );
        break;

    case 900:
    case -2700:
        m_Orient->SetSelection( 1 );
        break;

    case -900:
    case 2700:
        m_Orient->SetSelection( 2 );
        break;

    default:
        m_Orient->SetSelection( 3 );
        m_currentText->SetOrientation( KiROUND( m_OrientValue * 10.0 ) );
        custom_orientation = true;
        break;
    }
    m_OrientValue = 10.0 * m_currentText->GetOrientation();
    m_OrientValueCtrl->Enable( custom_orientation );
    m_OrientValidator.TransferToWindow();

    m_currentText->SetDrawCoord();

    LAYER_NUM layer = m_LayerSelectionCtrl->GetLayerSelection();
    m_currentText->SetLayer( ToLAYER_ID( layer ) );
    m_currentText->SetMirrored( IsBackLayer( m_currentText->GetLayer() ) );

#ifndef USE_WX_OVERLAY
    if( m_dc )     // Display new text
    {
        m_currentText->Draw( m_parent->GetCanvas(), m_dc, GR_XOR,
                (m_currentText->IsMoving()) ? MoveVector : wxPoint( 0, 0 ) );
    }
#else
    m_parent->Refresh();
#endif

    m_parent->OnModify();

    if( m_module )
        m_module->SetLastEditTime();

    return true;
}
Exemplo n.º 12
0
void MODULE::Flip( const wxPoint& aCentre )
{
    TEXTE_MODULE* text;

    // Move module to its final position:
    wxPoint finalPos = m_Pos;

    finalPos.y  = aCentre.y - ( finalPos.y - aCentre.y );     /// Mirror the Y position

    SetPosition( finalPos );

    // Flip layer
    SetLayer( FlipLayer( GetLayer() ) );

    // Reverse mirror orientation.
    NEGATE( m_Orient );
    NORMALIZE_ANGLE_POS( m_Orient );

    // Mirror pads to other side of board about the x axis, i.e. vertically.
    for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
        pad->Flip( m_Pos );

    // Mirror reference.
    text = m_Reference;
    text->m_Pos.y -= m_Pos.y;
    NEGATE( text->m_Pos.y );
    text->m_Pos.y += m_Pos.y;
    NEGATE(text->m_Pos0.y);
    NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient );
    text->SetLayer( FlipLayer( text->GetLayer() ) );
    text->m_Mirror = IsBackLayer( GetLayer() );

    // Mirror value.
    text = m_Value;
    text->m_Pos.y -= m_Pos.y;
    NEGATE( text->m_Pos.y );
    text->m_Pos.y += m_Pos.y;
    NEGATE( text->m_Pos0.y );
    NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient );
    text->SetLayer( FlipLayer( text->GetLayer() ) );
    text->m_Mirror = IsBackLayer( GetLayer() );

    // Reverse mirror module graphics and texts.
    for( EDA_ITEM* item = m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_EDGE_T:
            {
                EDGE_MODULE* em = (EDGE_MODULE*) item;

                wxPoint s = em->GetStart();
                s.y -= m_Pos.y;
                s.y  = -s.y;
                s.y += m_Pos.y;
                em->SetStart( s );

                wxPoint e = em->GetEnd();
                e.y -= m_Pos.y;
                e.y  = -e.y;
                e.y += m_Pos.y;
                em->SetEnd( e );

                NEGATE( em->m_Start0.y );
                NEGATE( em->m_End0.y );

                if( em->GetShape() == S_ARC )
                {
                    em->SetAngle( -em->GetAngle() );
                }

                em->SetLayer( FlipLayer( em->GetLayer() ) );
            }
            break;

        case PCB_MODULE_TEXT_T:
            text = (TEXTE_MODULE*) item;
            text->m_Pos.y -= m_Pos.y;
            NEGATE( text->m_Pos.y );
            text->m_Pos.y += m_Pos.y;
            NEGATE( text->m_Pos0.y );
            NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient );
            text->SetLayer( FlipLayer( text->GetLayer() ) );
            text->m_Mirror = IsBackLayer( GetLayer() );
            break;

        default:
            wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) );
            break;
        }
    }

    CalculateBoundingBox();
}
Exemplo n.º 13
0
int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
{
    BOARD_ITEM* text = NULL;
    const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
    BOARD_COMMIT commit( m_frame );

    // Add a VIEW_GROUP that serves as a preview for the new item
    SELECTION preview( m_view );
    m_view->Add( &preview );

    m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
    m_controls->ShowCursor( true );
    m_controls->SetSnapping( true );
    // do not capture or auto-pan until we start placing some text

    SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );

    Activate();
    m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT,
                        wxCURSOR_PENCIL, _( "Add text" ) );

    // Main loop: keep receiving events
    while( OPT_TOOL_EVENT evt = Wait() )
    {
        VECTOR2I cursorPos = m_controls->GetCursorPosition();

        if( evt->IsCancel() || evt->IsActivate() )
        {
            if( text )
            {
                // Delete the old text and have another try
                delete text;
                text = NULL;

                preview.Clear();

                m_controls->SetAutoPan( false );
                m_controls->CaptureCursor( false );
                m_controls->ShowCursor( true );
            }
            else
                break;

            if( evt->IsActivate() )  // now finish unconditionally
                break;
        }

        else if( text && evt->Category() == TC_COMMAND )
        {
            if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
            {
                text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() );
                m_view->Update( &preview );
            }
            // TODO rotate CCW
            else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
            {
                text->Flip( text->GetPosition() );
                m_view->Update( &preview );
            }
        }

        else if ( evt->IsClick( BUT_RIGHT ) )
        {
            showContextMenu();
        }

        else if( evt->IsClick( BUT_LEFT ) )
        {
            if( !text )
            {
                // Init the new item attributes
                if( m_editModules )
                {
                    TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) m_frame->GetModel() );

                    textMod->SetLayer( m_frame->GetActiveLayer() );
                    textMod->SetSize( dsnSettings.m_ModuleTextSize );
                    textMod->SetThickness( dsnSettings.m_ModuleTextWidth );
                    textMod->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );

                    DialogEditModuleText textDialog( m_frame, textMod, NULL );
                    bool placing;

                    RunMainStack( [&]() {
                        placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 );
                    } );

                    if( placing )
                        text = textMod;
                    else
                        delete textMod;
                }
                else
                {
                    TEXTE_PCB* textPcb = new TEXTE_PCB( m_frame->GetModel() );
                    // TODO we have to set IS_NEW, otherwise InstallTextPCB.. creates an undo entry :| LEGACY_CLEANUP
                    textPcb->SetFlags( IS_NEW );

                    LAYER_ID layer = m_frame->GetActiveLayer();
                    textPcb->SetLayer( layer );

                    // Set the mirrored option for layers on the BACK side of the board
                    if( IsBackLayer( layer ) )
                        textPcb->SetMirrored( true );

                    textPcb->SetSize( dsnSettings.m_PcbTextSize );
                    textPcb->SetThickness( dsnSettings.m_PcbTextWidth );
                    textPcb->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );

                    RunMainStack( [&]() {
                        getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL );
                    } );

                    if( textPcb->GetText().IsEmpty() )
                        delete textPcb;
                    else
                        text = textPcb;
                }

                if( text == NULL )
                    continue;

                m_controls->CaptureCursor( true );
                m_controls->SetAutoPan( true );
                //m_controls->ShowCursor( false );

                preview.Add( text );
            }
            else
            {
                //assert( text->GetText().Length() > 0 );
                //assert( text->GetSize().x > 0 && text->GetSize().y > 0 );

                text->ClearFlags();
                preview.Remove( text );

                commit.Add( text );
                commit.Push( _( "Place a text" ) );

                m_controls->CaptureCursor( false );
                m_controls->SetAutoPan( false );
                m_controls->ShowCursor( true );

                text = NULL;
            }
        }

        else if( text && evt->IsMotion() )
        {
            text->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );

            // Show a preview of the item
            m_view->Update( &preview );
        }
    }

    m_controls->ShowCursor( false );
    m_controls->SetSnapping( false );
    m_controls->SetAutoPan( false );
    m_controls->CaptureCursor( false );

    m_view->Remove( &preview );
    m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );

    return 0;

}