NS_IMETHODIMP nsMsgSearchDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder)
{
    int32_t rowCountBeforeSort = GetSize();

    if (!rowCountBeforeSort)
        return NS_OK;

    if (m_viewFlags & (nsMsgViewFlagsType::kThreadedDisplay |
                      nsMsgViewFlagsType::kGroupBySort))
    {
      // ### This forgets which threads were expanded, and is sub-optimal
      // since it rebuilds the thread objects.  
      m_sortType = sortType;
      m_sortOrder = sortOrder;
      return RebuildView(m_viewFlags);
    }

    nsMsgKey preservedKey;
    nsAutoTArray<nsMsgKey, 1> preservedSelection;
    SaveAndClearSelection(&preservedKey, preservedSelection);

    nsresult rv = nsMsgDBView::Sort(sortType,sortOrder);
    // the sort may have changed the number of rows
    // before we restore the selection, tell the tree
    // do this before we call restore selection
    // this is safe when there is no selection. 
    rv = AdjustRowCount(rowCountBeforeSort, GetSize());

    RestoreSelection(preservedKey, preservedSelection);
    if (mTree) mTree->Invalidate();

    NS_ENSURE_SUCCESS(rv,rv);
    return rv;
}
void LIB_EDIT_FRAME::SetCurPart( LIB_PART* aPart )
{
    if( !aPart && !m_my_part )
        return;

    m_toolManager->RunAction( EE_ACTIONS::clearSelection, true );

    if( m_my_part != aPart )
    {
        if( m_my_part )
            delete m_my_part;

        m_my_part = aPart;
    }

    // select the current component in the tree widget
    if( aPart )
        m_treePane->GetLibTree()->SelectLibId( aPart->GetLibId() );

    wxString partName = aPart ? aPart->GetName() : wxString();
    m_libMgr->SetCurrentPart( partName );

    // retain in case this wxFrame is re-opened later on the same PROJECT
    Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_PART, partName );

    // Ensure synchronized pin edit can be enabled only symbols with interchangeable units
    m_SyncPinEdit = aPart && aPart->IsMulti() && !aPart->UnitsLocked();

    m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
    RebuildView();
}
NS_IMETHODIMP nsMsgGroupView::OnHdrDeleted(nsIMsgDBHdr *aHdrDeleted, nsMsgKey aParentKey, int32_t aFlags,
                            nsIDBChangeListener *aInstigator)
{
  if (!(m_viewFlags & nsMsgViewFlagsType::kGroupBySort))
    return nsMsgDBView::OnHdrDeleted(aHdrDeleted, aParentKey, aFlags, aInstigator);

  // check if we're adding a header, and the current day has changed. If it has, we're just going to
  // close and re-open the view so things will be correctly categorized.
  if (m_dayChanged)
    return RebuildView(m_viewFlags);

  nsCOMPtr <nsIMsgThread> thread;
  nsMsgKey keyDeleted;
  aHdrDeleted->GetMessageKey(&keyDeleted);

  nsresult rv = GetThreadContainingMsgHdr(aHdrDeleted, getter_AddRefs(thread));
  NS_ENSURE_SUCCESS(rv, rv);
  nsMsgViewIndex viewIndexOfThread = GetIndexOfFirstDisplayedKeyInThread(
                                       thread, true); // yes to dummy node
  thread->RemoveChildHdr(aHdrDeleted, nullptr);

  nsMsgGroupThread *groupThread = static_cast<nsMsgGroupThread *>((nsIMsgThread *) thread);

  bool rootDeleted = viewIndexOfThread != nsMsgKey_None &&
    m_keys[viewIndexOfThread] == keyDeleted;
  rv = nsMsgDBView::OnHdrDeleted(aHdrDeleted, aParentKey, aFlags, aInstigator);
  if (groupThread->m_dummy)
  {
    if (!groupThread->NumRealChildren())
    {
      thread->RemoveChildAt(0); // get rid of dummy
      if (viewIndexOfThread != nsMsgKey_None)
      {
        RemoveByIndex(viewIndexOfThread);
        if (m_deletingRows)
          mIndicesToNoteChange.AppendElement(viewIndexOfThread);
      }
    }
    else if (rootDeleted)
    {
      // reflect new thread root into view.dummy row.
      nsCOMPtr<nsIMsgDBHdr> hdr;
      thread->GetChildHdrAt(0, getter_AddRefs(hdr));
      if (hdr)
      {
        nsMsgKey msgKey;
        hdr->GetMessageKey(&msgKey);
        SetMsgHdrAt(hdr, viewIndexOfThread, msgKey, m_flags[viewIndexOfThread], 0);
      }
    }
  }
  if (!groupThread->m_keys.Length())
  {
    nsString hashKey;
    rv = HashHdr(aHdrDeleted, hashKey);
    if (NS_SUCCEEDED(rv))
      m_groupsTable.Remove(hashKey);
  }
  return rv;
}
void LIB_EDIT_FRAME::OnSelectBodyStyle( wxCommandEvent& event )
{
    m_toolManager->RunAction( ACTIONS::cancelInteractive, true );
    m_toolManager->RunAction( EE_ACTIONS::clearSelection, true );

    m_convert = event.GetId() == ID_DE_MORGAN_NORMAL_BUTT ? 1 : 2;

    m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
    RebuildView();
}
NS_IMETHODIMP nsMsgQuickSearchDBView::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags)
{
  nsresult rv = NS_OK;
  // if the grouping has changed, rebuild the view
  if (m_viewFlags & nsMsgViewFlagsType::kGroupBySort ^
      (aViewFlags & nsMsgViewFlagsType::kGroupBySort))
    rv = RebuildView(aViewFlags);
  nsMsgDBView::SetViewFlags(aViewFlags);

  return rv;
}
NS_IMETHODIMP nsMsgXFVirtualFolderDBView::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags)
{
  nsresult rv = NS_OK;
  // if the grouping/threading has changed, rebuild the view
  if ((m_viewFlags & (nsMsgViewFlagsType::kGroupBySort |
                      nsMsgViewFlagsType::kThreadedDisplay)) !=
      (aViewFlags & (nsMsgViewFlagsType::kGroupBySort |
                     nsMsgViewFlagsType::kThreadedDisplay)))
    rv = RebuildView(aViewFlags);
  nsMsgDBView::SetViewFlags(aViewFlags);
  return rv;
}
void LIB_EDIT_FRAME::OnSelectUnit( wxCommandEvent& event )
{
    int i = event.GetSelection();

    if( ( i == wxNOT_FOUND ) || ( ( i + 1 ) == m_unit ) )
        return;

    m_toolManager->RunAction( ACTIONS::cancelInteractive, true );
    m_toolManager->RunAction( EE_ACTIONS::clearSelection, true );

    m_unit = i + 1;

    m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
    RebuildView();
}
NS_IMETHODIMP nsMsgGroupView::AddColumnHandler(const nsAString& column,
                                                 nsIMsgCustomColumnHandler* handler)
{
  nsMsgDBView::AddColumnHandler(column, handler);

  // If the sortType is byCustom and the desired custom column is the one just
  // registered, build the view.
  if (m_viewFlags & nsMsgViewFlagsType::kGroupBySort &&
      m_sortType == nsMsgViewSortType::byCustom)
  {
    nsAutoString curCustomColumn;
    GetCurCustomColumn(curCustomColumn);
    if (curCustomColumn == column)
      RebuildView(m_viewFlags);
  }

  return NS_OK;
}
NS_IMETHODIMP nsMsgGroupView::OnHdrFlagsChanged(nsIMsgDBHdr *aHdrChanged, uint32_t aOldFlags,
                                      uint32_t aNewFlags, nsIDBChangeListener *aInstigator)
{
  if (!(m_viewFlags & nsMsgViewFlagsType::kGroupBySort))
    return nsMsgDBView::OnHdrFlagsChanged(aHdrChanged, aOldFlags, aNewFlags,
                                          aInstigator);

  nsCOMPtr <nsIMsgThread> thread;

  // check if we're adding a header, and the current day has changed. If it has, we're just going to
  // close and re-open the view so things will be correctly categorized.
  if (m_dayChanged)
    return RebuildView(m_viewFlags);

  nsresult rv = GetThreadContainingMsgHdr(aHdrChanged, getter_AddRefs(thread));
  NS_ENSURE_SUCCESS(rv, rv);
  uint32_t deltaFlags = (aOldFlags ^ aNewFlags);
  if (deltaFlags & nsMsgMessageFlags::Read)
    thread->MarkChildRead(aNewFlags & nsMsgMessageFlags::Read);

  return nsMsgDBView::OnHdrFlagsChanged(aHdrChanged, aOldFlags, aNewFlags, aInstigator);
}
void LIB_EDIT_FRAME::pasteClipboard( const wxPoint& aOffset )
{
    LIB_PART* part = GetCurPart();

    if( !part || m_clipboard.GetCount() == 0 )
        return;

    for( unsigned int i = 0; i < m_clipboard.GetCount(); i++ )
    {
        // Append a copy to the current part, so the clipboard buffer might be pasted multiple times
        LIB_ITEM* item = (LIB_ITEM*) m_clipboard.GetItem( i )->Clone();
        item->SetParent( part );
        item->SetSelected();
        item->SetUnit( GetUnit() );
        part->AddDrawItem( item );
    }

    BlockMoveSelectedItems( aOffset, GetCurPart(), &GetScreen()->m_BlockLocate );
    RebuildView();
    GetCanvas()->Refresh();
    OnModify();
}
void LIB_EDIT_FRAME::HardRedraw()
{
    SyncLibraries( true );
    RebuildView();
}
Exemple #12
0
nsresult nsMsgGroupView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, bool ensureListed)
{
  if (!(m_viewFlags & nsMsgViewFlagsType::kGroupBySort))
    return nsMsgDBView::OnNewHeader(newHdr, aParentKey, ensureListed);

  // check if we're adding a header, and the current day has changed. If it has, we're just going to
  // close and re-open the view so things will be correctly categorized.
  if (m_dayChanged)
    return RebuildView(m_viewFlags);

  bool newThread;
  nsMsgGroupThread *thread = AddHdrToThread(newHdr, &newThread);
  if (thread)
  {
    // find the view index of (the root node of) the thread
    nsMsgViewIndex threadIndex = ThreadIndexOfMsgHdr(newHdr);
    // may need to fix thread counts
    if (threadIndex != nsMsgViewIndex_None)
    {
      if (newThread)
      {
        // AddHdrToThread creates the header elided, so we need to un-elide it
        //  if we want it expanded.
        if(m_viewFlags & nsMsgViewFlagsType::kExpandAll)
          m_flags[threadIndex] &= ~nsMsgMessageFlags::Elided;
      }
      else
      {
        m_flags[threadIndex] |= MSG_VIEW_FLAG_HASCHILDREN
                                | MSG_VIEW_FLAG_ISTHREAD;
      }

      int32_t numRowsToInvalidate = 1;
      // if the thread is expanded (not elided), we should add the header to
      //  the view.
      if (! (m_flags[threadIndex] & nsMsgMessageFlags::Elided))
      {
        uint32_t msgIndexInThread = thread->FindMsgHdr(newHdr);
        bool insertedAtThreadRoot = !msgIndexInThread;
        // Add any new display node and potentially fix-up changes in the root.
        // (If this is a new thread and we are not using a dummy row, the only
        //  node to display is the root node which has already been added by
        //  AddHdrToThread.  And since there is just the one, no change in root
        //  could have occurred, so we have nothing to do.)
        if (!newThread || GroupViewUsesDummyRow())
        {
          // we never want to insert/update the root node, because
          //  AddHdrToThread has already done that for us (in all cases).
          if (insertedAtThreadRoot)
            msgIndexInThread++;
          // If this header is the new parent of the thread... AND
          // If we are not using a dummy row, this means we need to append our
          //  old node as the first child of the new root.
          // (If we are using a dummy row, the old node's "content" node already
          //  exists (at position threadIndex + 1) and we need to insert the
          //  "content" copy of the new root node there, pushing our old
          //  "content" node down.)
          // Example mini-diagrams, wrapping the to-add thing with ()
          //  No dummy row; we had: [A], now we have [B], we want [B (A)].
          //  Dummy row; we had: [A A], now we have [B A], we want [B (B) A].
          //  (Coming into this we're adding 'B')
          if (!newThread && insertedAtThreadRoot && !GroupViewUsesDummyRow())
          {
            // grab a copy of the old root node ('A') from the thread so we can
            //  insert it. (offset msgIndexInThread=1 is the right thing; we are
            //  non-dummy.)
            thread->GetChildHdrAt(msgIndexInThread, &newHdr);
          } // nothing to do for dummy case, we're already inserting 'B'.
          nsMsgKey msgKey;
          uint32_t msgFlags;
          newHdr->GetMessageKey(&msgKey);
          newHdr->GetFlags(&msgFlags);
          InsertMsgHdrAt(threadIndex + msgIndexInThread, newHdr, msgKey,
                         msgFlags, 1);
        }
        // the call to NoteChange() has to happen after we add the key
        // as NoteChange() will call RowCountChanged() which will call our GetRowCount()
        // (msgIndexInThread states.  new thread: 0, old thread at root: 1)
        if (newThread && GroupViewUsesDummyRow())
          NoteChange(threadIndex, 2, nsMsgViewNotificationCode::insertOrDelete);
        else
          NoteChange(threadIndex + msgIndexInThread, 1,
                     nsMsgViewNotificationCode::insertOrDelete);
        numRowsToInvalidate = msgIndexInThread;
      }
      // we still need the addition notification for new threads when elided
      else if (newThread)
      {
        NoteChange(threadIndex, 1,
                   nsMsgViewNotificationCode::insertOrDelete);
      }
      NoteChange(threadIndex, numRowsToInvalidate, nsMsgViewNotificationCode::changed);
    }
  }
  // if thread is expanded, we need to add hdr to view...
  return NS_OK;
}
void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
{
    BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate;
    wxPoint pt;

    if( !m_canvas->IsMouseCaptured() )
    {
        DisplayError( this, wxT( "HandleBlockPLace : m_mouseCaptureCallback = NULL" ) );
    }

    block->SetState( STATE_BLOCK_STOP );

    switch( block->GetCommand() )
    {
    case  BLOCK_IDLE:
        break;

    case BLOCK_DRAG:                // Drag
    case BLOCK_DRAG_ITEM:
    case BLOCK_MOVE:                // Move
    case BLOCK_DUPLICATE:           // Duplicate
        if( GetCurPart() && !block->AppendUndo() )
            SaveCopyInUndoList( GetCurPart() );

        pt = block->GetMoveVector();

        if( GetCurPart() )
            BlockMoveSelectedItems( pt, GetCurPart(), block );

        block->ClearItemsList();
        break;

    case BLOCK_PASTE:       // Paste (recopy the last block saved)
        if( GetCurPart() )
            SaveCopyInUndoList( GetCurPart() );

        pt = block->GetMoveVector();

        pasteClipboard( pt );

        block->ClearItemsList();
        break;

    case BLOCK_ZOOM:        // Handled by HandleBlockEnd
    case BLOCK_DELETE:
    case BLOCK_COPY:
    case BLOCK_ABORT:
    default:
        break;
    }

    RebuildView();
    GetCanvas()->Refresh();
    OnModify();

    block->SetState( STATE_NO_BLOCK );
    block->SetCommand( BLOCK_IDLE );
    GetScreen()->SetCurItem( NULL );
    m_canvas->EndMouseCapture( GetToolId(), GetGalCanvas()->GetCurrentCursor(), wxEmptyString, false );

    GetCanvas()->GetView()->ClearPreview();
    GetCanvas()->GetView()->ClearHiddenFlags();
}
bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
{
    int ItemCount = 0;
    bool nextCmd = false;
    BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate;
    wxPoint pt;

    auto panel =static_cast<SCH_DRAW_PANEL*>(m_canvas);
    auto view = panel->GetView();
    auto area = view->GetSelectionArea();

    auto start = area->GetOrigin();
    auto end = area->GetEnd();

    block->SetOrigin( wxPoint( start.x, start.y ) );
    block->SetEnd( wxPoint( end.x, end.y ) );

    view->ShowSelectionArea( false );
    view->ClearHiddenFlags();

    if( block->GetCount() )
    {
        BLOCK_STATE_T state     = block->GetState();
        BLOCK_COMMAND_T command = block->GetCommand();

        m_canvas->CallEndMouseCapture( aDC );

        block->SetState( state );
        block->SetCommand( command );
        m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand );

        if( block->GetCommand() != BLOCK_ABORT
            && block->GetCommand() != BLOCK_DUPLICATE
            && block->GetCommand() != BLOCK_COPY
            && block->GetCommand() != BLOCK_CUT
            && block->GetCommand() != BLOCK_DELETE )
        {
            SetCrossHairPosition( block->GetEnd() );
            m_canvas->MoveCursorToCrossHair();
        }
    }

    if( m_canvas->IsMouseCaptured() )
    {
        switch( block->GetCommand() )
        {
        case  BLOCK_IDLE:
            DisplayError( this, wxT( "Error in HandleBlockPLace" ) );
            break;

        case BLOCK_DRAG:        // Drag
        case BLOCK_DRAG_ITEM:
        case BLOCK_MOVE:        // Move
        case BLOCK_DUPLICATE:   // Duplicate
            if( GetCurPart() )
                ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );

            if( ItemCount )
            {
                nextCmd = true;
                block->SetState( STATE_BLOCK_MOVE );

                if( block->GetCommand() == BLOCK_DUPLICATE )
                {
                    if( block->AppendUndo() )
                        ; // UR_LIBEDIT saves entire state, so no need to append anything more
                    else
                    {
                        SaveCopyInUndoList( GetCurPart(), UR_LIBEDIT );
                        block->SetAppendUndo();
                    }

                    BlockCopySelectedItems( pt, GetCurPart(), block );
                    block->SetLastCursorPosition( GetCrossHairPosition( true ) );
                }

                m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
                m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
            }
            else
            {
                m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
                m_canvas->SetMouseCapture( NULL, NULL );
            }
            break;

        case BLOCK_COPY:    // Save a copy of items in the clipboard buffer
        case BLOCK_CUT:
            if( GetCurPart() )
                ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );

            if( ItemCount )
            {
                copySelectedItems();
                auto cmd = block->GetCommand();

                if( cmd == BLOCK_COPY )
                {
                    BlockClearSelectedItems( GetCurPart(), block );
                    block->ClearItemsList();
                }
                else if( cmd == BLOCK_CUT )
                {
                    if( block->AppendUndo() )
                        ; // UR_LIBEDIT saves entire state, so no need to append anything more
                    else
                    {
                        SaveCopyInUndoList( GetCurPart(), UR_LIBEDIT );
                        block->SetAppendUndo();
                    }

                    BlockDeleteSelectedItems( GetCurPart(), block );
                    RebuildView();
                    GetCanvas()->Refresh();
                    OnModify();
                }
            }
            break;

        case BLOCK_DELETE:     // Delete
            if( GetCurPart() )
                ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );

            if( block->AppendUndo() )
                ; // UR_LIBEDIT saves entire state, so no need to append anything more
            else if( ItemCount )
            {
                SaveCopyInUndoList( GetCurPart(), UR_LIBEDIT );
                block->SetAppendUndo();
            }

            if( GetCurPart() )
            {
                BlockDeleteSelectedItems( GetCurPart(), block );
                RebuildView();
                GetCanvas()->Refresh();
                OnModify();
            }
            break;

        case BLOCK_PASTE:
        case BLOCK_ROTATE:
        case BLOCK_MIRROR_X:
        case BLOCK_MIRROR_Y:
        case BLOCK_FLIP:
            wxFAIL; // should not happen
            break;

        case BLOCK_ZOOM:     // Window Zoom
            Window_Zoom( *block );
            break;

        case BLOCK_ABORT:
            break;

        case BLOCK_SELECT_ITEMS_ONLY:
            break;

        case BLOCK_PRESELECT_MOVE:          // not used in LibEdit
        case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema
        case BLOCK_MOVE_EXACT:              // not used in Eeschema
            break;
        }
    }

    if( block->GetCommand() == BLOCK_ABORT )
    {
        GetScreen()->ClearDrawingState();
    }

    if( !nextCmd )
    {
        if( block->GetCommand() != BLOCK_SELECT_ITEMS_ONLY && GetCurPart() )
            BlockClearSelectedItems( GetCurPart(), block );

        GetScreen()->ClearBlockCommand();
        GetScreen()->SetCurItem( NULL );
        m_canvas->EndMouseCapture( GetToolId(), GetGalCanvas()->GetCurrentCursor(), wxEmptyString,
                                   false );
    }

    view->ShowSelectionArea( false );
    view->ShowPreview( nextCmd );

    return nextCmd;
}