← Back to team overview

kicad-developers team mailing list archive

[PATCH] Allow to edit an schematic item while dragging

 

In eeschema, it is not possible to access the Edit Schematic Item dialog
while dragging an item because the dragging is implemented by simulating
a block command, and the edit functionality is missing in the block
context menu, and the related hotkeys are inactive as well.

For schematic components (SCH_COMPONENT), the dragged block is composed
by the component plus its connections (if any). For other schematic
items that can be edited, like labels or text, is composed by the item
itself. As the block to be dragged is formed in two steps: first the
items (SCH_SCREEN::UpdatePickList), next its connections if the item is
a SCH_COMPONENT (SCH_SCREEN::SelectBlockItems), we can detect if the
block was originally composed by only one item.

The attached patch allows to edit an schematic item that constitutes a
block by adding the Edit Item entry to the block context menu,
independently of the operation being done: dragging, moving or copying
the block. Hotkeys for editing (HK_EDIT, HK_EDIT_COMPONENT_{VALUE,
REFERENCE, FOOTPRINT}) should work as well. For schematic components, it
takes into account that some properties should be not edited while
dragging, like the Chip Name.  In principle, for text, and local,
hierarchical and global labels all the fields are editable, but
it can be changed if needed.

More details about the patch:

- When updating the list of components of the block
(SCH_SCREEN::UpdatePickList), if the block is composed of only one item,
set the current item to point to that item (BASE_SCREEN::SetCurItem).

- When the user clicks the mouse right button to show the context menu,
check if there is an active block of only one item
(screen->IsBlockActive() && screen->GetCurrentItem() != NULL), if so,
add the Edit entry to the block context menu. 

- In the Edit SCH_COMPONENT menu, if the current item is being dragged
(flag IS_DRAGGED), disable some fields.

- As for blocks composed by one item, the SCH_SCREEN::GetCurItem is now
different from NULL, it is necessary to:
 * Check if a block exists before starting a Move Item command initiated
via hotkey ('M')(SCH_EDIT_FRAME::OnMoveItem).
 * Remove the check for SCH_SCREEN::GetCurItemfor == NULL before
starting an orient and rotate block operation
(SCH_EDIT_FRAME::On{Rotate, Orient}).

=== modified file 'eeschema/dialogs/dialog_edit_component_in_schematic.cpp'
--- eeschema/dialogs/dialog_edit_component_in_schematic.cpp	2012-04-16 17:39:32 +0000
+++ eeschema/dialogs/dialog_edit_component_in_schematic.cpp	2012-12-27 15:54:40 +0000
@@ -539,6 +539,15 @@
 
     copyOptionsToPanel();
 
+    // disable some options inside the edit dialog
+    // which can cause problems while dragging
+    if( m_Cmp->IsDragging() )
+    {
+        orientationRadioBox->Disable();
+        mirrorRadioBox->Disable();
+        chipnameTextCtrl->Disable();
+    }
+
     // put focus on the list ctrl
     fieldListCtrl->SetFocus();
 

=== modified file 'eeschema/onrightclick.cpp'
--- eeschema/onrightclick.cpp	2012-12-08 19:36:28 +0000
+++ eeschema/onrightclick.cpp	2012-12-27 15:54:40 +0000
@@ -59,6 +59,7 @@
 static void AddMenusForLabel( wxMenu* PopMenu, SCH_LABEL* Label );
 static void AddMenusForGLabel( wxMenu* PopMenu, SCH_GLOBALLABEL* GLabel );
 static void AddMenusForHLabel( wxMenu* PopMenu, SCH_HIERLABEL* GLabel );
+static void AddMenusForEditComponent( wxMenu* PopMenu, SCH_COMPONENT* Component );
 static void AddMenusForComponent( wxMenu* PopMenu, SCH_COMPONENT* Component );
 static void AddMenusForComponentField( wxMenu* PopMenu, SCH_FIELD* Field );
 static void AddMenusForMarkers( wxMenu* aPopMenu, SCH_MARKER* aMarker, SCH_EDIT_FRAME* aFrame );
@@ -75,6 +76,7 @@
 {
     SCH_ITEM* item = GetScreen()->GetCurItem();
     bool      BlockActive = GetScreen()->IsBlockActive();
+    wxString msg;
 
     // Do not start a block command  on context menu.
     m_canvas->SetCanStartBlock( -1 );
@@ -83,6 +85,48 @@
     {
         AddMenusForBlock( PopMenu, this );
         PopMenu->AppendSeparator();
+
+        // If we have a block containing only one main element
+        // we append its edition submenu
+        if( item != NULL )
+        {
+            switch( item->Type() )
+            {
+                case SCH_COMPONENT_T:
+                    AddMenusForEditComponent( PopMenu, (SCH_COMPONENT *) item );
+                    PopMenu->AppendSeparator();
+                    break;
+
+                case SCH_TEXT_T:
+                    msg = AddHotkeyName( _( "Edit Text" ), s_Schematic_Hokeys_Descr, HK_EDIT );
+                    AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
+                    PopMenu->AppendSeparator();
+                    break;
+
+                case SCH_LABEL_T:
+                    msg = AddHotkeyName( _( "Edit Label" ), s_Schematic_Hokeys_Descr, HK_EDIT );
+                    AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
+                    PopMenu->AppendSeparator();
+                    break;
+
+                case SCH_GLOBAL_LABEL_T:
+                    msg = AddHotkeyName( _( "Edit Global Label" ), s_Schematic_Hokeys_Descr,
+                                         HK_EDIT );
+                    AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
+                    PopMenu->AppendSeparator();
+                    break;
+
+                case SCH_HIERARCHICAL_LABEL_T:
+                    msg = AddHotkeyName( _( "Edit Hierarchical Label" ), s_Schematic_Hokeys_Descr,
+                                         HK_EDIT );
+                    AddMenuItem( PopMenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_text_xpm ) );
+                    PopMenu->AppendSeparator();
+                    break;
+
+                default:
+                    break;
+            }
+        }
         return true;
     }
 
@@ -295,13 +339,9 @@
 
     wxString       msg;
     LIB_ALIAS*     libEntry;
-    LIB_COMPONENT* libComponent = NULL;
 
     libEntry = CMP_LIBRARY::FindLibraryEntry( Component->GetLibName() );
 
-    if( libEntry )
-        libComponent = libEntry->GetComponent();
-
     if( !Component->GetFlags() )
     {
         msg = _( "Move Component" );
@@ -327,6 +367,39 @@
     AddMenuItem( PopMenu, orientmenu, ID_POPUP_SCH_GENERIC_ORIENT_CMP,
                  _( "Orient Component" ), KiBitmap( orient_xpm ) );
 
+    AddMenusForEditComponent( PopMenu, Component );
+
+    if( !Component->GetFlags() )
+    {
+        msg = AddHotkeyName( _( "Copy Component" ), s_Schematic_Hokeys_Descr,
+                             HK_COPY_COMPONENT_OR_LABEL );
+        AddMenuItem( PopMenu, ID_POPUP_SCH_COPY_ITEM, msg, KiBitmap( copy_button_xpm ) );
+        msg = AddHotkeyName( _( "Delete Component" ), s_Schematic_Hokeys_Descr, HK_DELETE );
+        AddMenuItem( PopMenu, ID_POPUP_SCH_DELETE_CMP, msg, KiBitmap( delete_xpm ) );
+    }
+
+    if( libEntry && !libEntry->GetDocFileName().IsEmpty() )
+        AddMenuItem( PopMenu, ID_POPUP_SCH_DISPLAYDOC_CMP, _( "Doc" ), KiBitmap( datasheet_xpm ) );
+}
+
+
+void AddMenusForEditComponent( wxMenu* PopMenu, SCH_COMPONENT* Component )
+{
+    if( Component->Type() != SCH_COMPONENT_T )
+    {
+        wxASSERT( 0 );
+        return;
+    }
+
+    wxString       msg;
+    LIB_ALIAS*     libEntry;
+    LIB_COMPONENT* libComponent = NULL;
+
+    libEntry = CMP_LIBRARY::FindLibraryEntry( Component->GetLibName() );
+
+    if( libEntry )
+        libComponent = libEntry->GetComponent();
+
     wxMenu* editmenu = new wxMenu;
     msg = AddHotkeyName( _( "Edit" ), s_Schematic_Hokeys_Descr, HK_EDIT );
     AddMenuItem( editmenu, ID_SCH_EDIT_ITEM, msg, KiBitmap( edit_component_xpm ) );
@@ -384,17 +457,6 @@
     AddMenuItem( PopMenu, editmenu, ID_SCH_EDIT_ITEM,
                  _( "Edit Component" ), KiBitmap( edit_component_xpm ) );
 
-    if( !Component->GetFlags() )
-    {
-        msg = AddHotkeyName( _( "Copy Component" ), s_Schematic_Hokeys_Descr,
-                             HK_COPY_COMPONENT_OR_LABEL );
-        AddMenuItem( PopMenu, ID_POPUP_SCH_COPY_ITEM, msg, KiBitmap( copy_button_xpm ) );
-        msg = AddHotkeyName( _( "Delete Component" ), s_Schematic_Hokeys_Descr, HK_DELETE );
-        AddMenuItem( PopMenu, ID_POPUP_SCH_DELETE_CMP, msg, KiBitmap( delete_xpm ) );
-    }
-
-    if( libEntry && !libEntry->GetDocFileName().IsEmpty() )
-        AddMenuItem( PopMenu, ID_POPUP_SCH_DISPLAYDOC_CMP, _( "Doc" ), KiBitmap( datasheet_xpm ) );
 }
 
 

=== modified file 'eeschema/sch_screen.cpp'
--- eeschema/sch_screen.cpp	2012-09-28 17:47:41 +0000
+++ eeschema/sch_screen.cpp	2012-12-27 15:54:40 +0000
@@ -774,6 +774,7 @@
     for( ; ii < last_select_id; ii++ )
     {
         item = (SCH_ITEM*)pickedlist->GetPickedItem( ii );
+        item->SetFlags( IS_DRAGGED );
 
         if( item->Type() == SCH_LINE_T )
         {
@@ -858,6 +859,8 @@
 {
     ITEM_PICKER picker;
     EDA_RECT area;
+    unsigned count;
+
     area.SetOrigin( m_BlockLocate.GetOrigin() );
     area.SetSize( m_BlockLocate.GetSize() );
     area.Normalize();
@@ -872,7 +875,19 @@
         }
     }
 
-    return m_BlockLocate.GetCount();
+    // if the block is composed of one item,
+    // select it as the current item
+    count =  m_BlockLocate.GetCount();
+    if( count == 1 )
+    {
+        SetCurItem( (SCH_ITEM*) m_BlockLocate.GetItem( 0 ) );
+    }
+    else
+    {
+        SetCurItem( NULL );
+    }
+
+    return count;
 }
 
 

=== modified file 'eeschema/schedit.cpp'
--- eeschema/schedit.cpp	2012-12-08 17:24:49 +0000
+++ eeschema/schedit.cpp	2012-12-27 15:54:40 +0000
@@ -384,6 +384,12 @@
     SCH_SCREEN* screen = GetScreen();
     SCH_ITEM*   item = screen->GetCurItem();
 
+    if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+    {
+        // trying to move an item when there is a block at the same time is not acceptable
+        return;
+    }
+
     if( item == NULL )
     {
         // If we didn't get here by a hot key, then something has gone wrong.
@@ -725,15 +731,15 @@
 
     INSTALL_UNBUFFERED_DC( dc, m_canvas );
 
+    // Allows block rotate operation on hot key.
+    if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+    {
+        HandleBlockEndByPopUp( BLOCK_ROTATE, &dc );
+        return;
+    }
+
     if( item == NULL )
     {
-        // Allows block rotate operation on hot key.
-        if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
-        {
-            HandleBlockEndByPopUp( BLOCK_ROTATE, &dc );
-            return;
-        }
-
         // If we didn't get here by a hot key, then something has gone wrong.
         if( aEvent.GetInt() == 0 )
             return;
@@ -965,9 +971,6 @@
         wxFAIL_MSG( wxString::Format( wxT( "Cannot drag schematic item type %s." ),
                                       GetChars( item->GetClass() ) ) );
     }
-
-    // Since the drag is actually a block command, clear the current item.
-    screen->SetCurItem( NULL );
 }
 
 
@@ -978,21 +981,21 @@
 
     INSTALL_UNBUFFERED_DC( dc, m_canvas );
 
+    // Allows block rotate operation on hot key.
+    if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+    {
+        if( aEvent.GetId() == ID_SCH_MIRROR_X )
+            HandleBlockEndByPopUp( BLOCK_MIRROR_X, &dc );
+        else if( aEvent.GetId() == ID_SCH_MIRROR_Y )
+            HandleBlockEndByPopUp( BLOCK_MIRROR_Y, &dc );
+        else
+            wxFAIL_MSG( wxT( "Unknown block oriention command ID." ) );
+
+        return;
+    }
+
     if( item == NULL )
     {
-        // Allows block rotate operation on hot key.
-        if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
-        {
-            if( aEvent.GetId() == ID_SCH_MIRROR_X )
-                HandleBlockEndByPopUp( BLOCK_MIRROR_X, &dc );
-            else if( aEvent.GetId() == ID_SCH_MIRROR_Y )
-                HandleBlockEndByPopUp( BLOCK_MIRROR_Y, &dc );
-            else
-                wxFAIL_MSG( wxT( "Unknown block oriention command ID." ) );
-
-            return;
-        }
-
         // If we didn't get here by a hot key, then something has gone wrong.
         if( aEvent.GetInt() == 0 )
             return;


Follow ups