From e6b0a6abca4ef283d0c4072d45a9363872be578b Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 2 Sep 2023 22:13:48 +0100 Subject: [PATCH] ADDED: lib tree previews. Fixes https://gitlab.com/kicad/code/kicad/-/issues/2418 --- common/draw_panel_gal.cpp | 40 +++--- common/widgets/lib_tree.cpp | 128 +++++++++++++++++- common/widgets/wx_panel.cpp | 16 ++- eeschema/dialogs/dialog_choose_symbol.cpp | 2 +- eeschema/dialogs/dialog_rescue_each.cpp | 6 +- .../symbol_tree_synchronizing_adapter.cpp | 39 ++++++ eeschema/symbol_tree_synchronizing_adapter.h | 3 + eeschema/widgets/symbol_diff_widget.cpp | 2 +- eeschema/widgets/symbol_preview_widget.cpp | 67 +++++---- eeschema/widgets/symbol_preview_widget.h | 2 +- include/lib_tree_model_adapter.h | 5 +- include/widgets/lib_tree.h | 13 ++ include/widgets/wx_panel.h | 8 ++ .../dialogs/panel_pcbnew_color_settings.cpp | 15 +- pcbnew/dialogs/panel_pcbnew_color_settings.h | 3 +- pcbnew/footprint_preview_panel.cpp | 22 +-- pcbnew/footprint_preview_panel.h | 8 +- pcbnew/fp_tree_synchronizing_adapter.cpp | 27 ++++ pcbnew/fp_tree_synchronizing_adapter.h | 3 + pcbnew/pcbnew.cpp | 2 +- 20 files changed, 325 insertions(+), 86 deletions(-) diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 75dbac0c33..f6a5e5712b 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -391,6 +391,25 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool aEraseBackground, const wxRect* aRect ) void EDA_DRAW_PANEL_GAL::ForceRefresh() { + if( !m_drawingEnabled ) + { + if( m_gal && m_gal->IsInitialized() ) + { + Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), nullptr, + this ); + + Connect( wxEVT_IDLE, wxIdleEventHandler( EDA_DRAW_PANEL_GAL::onIdle ), nullptr, this ); + + m_drawingEnabled = true; + } + else + { + // Try again soon + m_refreshTimer.StartOnce( 100 ); + return; + } + } + DoRePaint(); } @@ -613,26 +632,7 @@ void EDA_DRAW_PANEL_GAL::onIdle( wxIdleEvent& aEvent ) void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent ) { - if( !m_drawingEnabled ) - { - if( m_gal && m_gal->IsInitialized() ) - { - Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), nullptr, - this ); - - Connect( wxEVT_IDLE, wxIdleEventHandler( EDA_DRAW_PANEL_GAL::onIdle ), nullptr, this ); - - m_drawingEnabled = true; - } - else - { - // Try again soon - m_refreshTimer.StartOnce( 100 ); - return; - } - } - - DoRePaint(); + ForceRefresh(); } diff --git a/common/widgets/lib_tree.cpp b/common/widgets/lib_tree.cpp index ceef6ed4b8..52d6a631f7 100644 --- a/common/widgets/lib_tree.cpp +++ b/common/widgets/lib_tree.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include constexpr int RECENT_SEARCHES_MAX = 10; @@ -54,10 +54,14 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, const wxString& aRecentSearchesKey, LIB_T m_details_ctrl( nullptr ), m_inTimerEvent( false ), m_recentSearchesKey( aRecentSearchesKey ), - m_skipNextRightClick( false ) + m_skipNextRightClick( false ), + m_previewWindow( nullptr ) { wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); + m_hoverTimer.SetOwner( this ); + Bind( wxEVT_TIMER, &LIB_TREE::onHoverTimer, this, m_hoverTimer.GetId() ); + // Search text control if( aFlags & SEARCH ) { @@ -177,6 +181,10 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, const wxString& aRecentSearchesKey, LIB_T m_tree_ctrl->Bind( wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, &LIB_TREE::onHeaderContextMenu, this ); + // wxDataViewCtrl eats its mouseMoved events, so we're forced to use idle events to track + // the hover state + Bind( wxEVT_IDLE, &LIB_TREE::onIdle, this ); + // Process hotkeys when the tree control has focus: m_tree_ctrl->Bind( wxEVT_CHAR_HOOK, &LIB_TREE::onTreeCharHook, this ); @@ -215,6 +223,9 @@ LIB_TREE::~LIB_TREE() { // Stop the timer during destruction early to avoid potential race conditions (that do happen) m_debounceTimer->Stop(); + + m_hoverTimer.Stop(); + hidePreview(); } @@ -590,6 +601,111 @@ void LIB_TREE::onQueryMouseMoved( wxMouseEvent& aEvent ) } +#define PREVIEW_SIZE wxSize( 240, 200 ) + + +void LIB_TREE::showPreview( wxDataViewItem aItem ) +{ + if( aItem.IsOk() && m_adapter->HasPreview( aItem ) ) + { + m_hoverItem = aItem; + + wxWindow* topLevelParent = m_parent; + + while( topLevelParent && !topLevelParent->IsTopLevel() ) + topLevelParent = topLevelParent->GetParent(); + + m_previewWindow = new wxPopupWindow( topLevelParent ); + m_previewWindow->SetPosition( wxPoint( m_tree_ctrl->GetScreenRect().GetRight() - 10, + wxGetMousePosition().y - PREVIEW_SIZE.y / 2 ) ); + m_previewWindow->SetSize( PREVIEW_SIZE ); + + m_previewWindow->Freeze(); + m_previewWindow->Show(); + + m_adapter->ShowPreview( m_previewWindow, aItem ); + m_previewWindow->Thaw(); + } +} + + +void LIB_TREE::hidePreview() +{ + m_hoverItem = wxDataViewItem(); + + if( m_previewWindow ) + { + m_previewWindow->Hide(); + m_previewWindow->Destroy(); + m_previewWindow = nullptr; + } +} + + +void LIB_TREE::onIdle( wxIdleEvent& aEvent ) +{ + // The wxDataViewCtrl won't give us its mouseMoved events so we're forced to use idle + // events to track the hover state + + wxWindow* topLevelParent = m_parent; + + while( topLevelParent && !topLevelParent->IsTopLevel() ) + topLevelParent = topLevelParent->GetParent(); + + wxWindow* topLevelFocus = FindFocus(); + + while( topLevelFocus && !topLevelFocus->IsTopLevel() ) + topLevelFocus = topLevelFocus->GetParent(); + + wxPoint screenPos = wxGetMousePosition(); + wxRect screenRect = m_tree_ctrl->GetScreenRect(); + + if( topLevelFocus != topLevelParent || !screenRect.Contains( screenPos ) ) + { + m_hoverTimer.Stop(); + hidePreview(); + return; + } + + wxPoint clientPos = m_tree_ctrl->ScreenToClient( screenPos ); + + if( m_hoverItem.IsOk() ) + { + wxDataViewItem item; + wxDataViewColumn* col = nullptr; + m_tree_ctrl->HitTest( clientPos, item, col ); + + if( item != m_hoverItem ) + { + hidePreview(); + m_hoverPos = clientPos; + showPreview( item ); + } + + return; + } + + if( m_hoverPos != clientPos ) + { + m_hoverPos = clientPos; + m_hoverTimer.Start( 400, wxTIMER_ONE_SHOT ); + } +} + + +void LIB_TREE::onHoverTimer( wxTimerEvent& aEvent ) +{ + hidePreview(); + + wxDataViewItem item; + wxDataViewColumn* col = nullptr; + m_tree_ctrl->HitTest( m_hoverPos, item, col ); + + if( item != m_tree_ctrl->GetSelection() ) + showPreview( item ); +} + + void LIB_TREE::onTreeCharHook( wxKeyEvent& aKeyStroke ) { onQueryCharHook( aKeyStroke ); @@ -628,6 +744,8 @@ void LIB_TREE::onTreeSelect( wxDataViewEvent& aEvent ) void LIB_TREE::onTreeActivate( wxDataViewEvent& aEvent ) { + hidePreview(); + if( !GetSelectedLibId().IsValid() ) toggleExpand( m_tree_ctrl->GetSelection() ); // Expand library/part units subtree else @@ -644,6 +762,8 @@ void LIB_TREE::onDetailsLink( wxHtmlLinkEvent& aEvent ) void LIB_TREE::onPreselect( wxCommandEvent& aEvent ) { + hidePreview(); + if( m_details_ctrl ) { int unit = 0; @@ -661,6 +781,8 @@ void LIB_TREE::onPreselect( wxCommandEvent& aEvent ) void LIB_TREE::onItemContextMenu( wxDataViewEvent& aEvent ) { + hidePreview(); + if( m_skipNextRightClick ) { m_skipNextRightClick = false; @@ -731,6 +853,8 @@ void LIB_TREE::onItemContextMenu( wxDataViewEvent& aEvent ) void LIB_TREE::onHeaderContextMenu( wxDataViewEvent& aEvent ) { + hidePreview(); + ACTION_MENU menu( true, nullptr ); menu.Add( ACTIONS::selectColumns ); diff --git a/common/widgets/wx_panel.cpp b/common/widgets/wx_panel.cpp index b403d21901..48101118a5 100644 --- a/common/widgets/wx_panel.cpp +++ b/common/widgets/wx_panel.cpp @@ -24,7 +24,6 @@ #include #include #include -#include "gal/color4d.h" WX_PANEL::WX_PANEL( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : @@ -32,7 +31,8 @@ WX_PANEL::WX_PANEL( wxWindow* parent, wxWindowID id, const wxPoint& pos, const w m_leftBorder( false ), m_rightBorder( false ), m_topBorder( false ), - m_bottomBorder( false ) + m_bottomBorder( false ), + m_borderColor( KIGFX::COLOR4D::UNSPECIFIED ) { this->Connect( wxEVT_PAINT, wxPaintEventHandler( WX_PANEL::OnPaint ) ); } @@ -49,9 +49,15 @@ void WX_PANEL::OnPaint( wxPaintEvent& event ) wxRect rect( wxPoint( 0, 0 ), GetClientSize() ); wxPaintDC dc( this ); - KIGFX::COLOR4D bg = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ); - KIGFX::COLOR4D fg = wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ); - KIGFX::COLOR4D border = fg.Mix( bg, 0.18 ); + KIGFX::COLOR4D border = m_borderColor; + + if( border == KIGFX::COLOR4D::UNSPECIFIED ) + { + KIGFX::COLOR4D bg = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ); + KIGFX::COLOR4D fg = wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ); + border = fg.Mix( bg, 0.18 ); + } + dc.SetPen( wxPen( border.ToColour(), 1 ) ); if( m_leftBorder ) diff --git a/eeschema/dialogs/dialog_choose_symbol.cpp b/eeschema/dialogs/dialog_choose_symbol.cpp index 24006da0f3..23fb47df29 100644 --- a/eeschema/dialogs/dialog_choose_symbol.cpp +++ b/eeschema/dialogs/dialog_choose_symbol.cpp @@ -294,7 +294,7 @@ wxPanel* DIALOG_CHOOSE_SYMBOL::ConstructRightPanel( wxWindow* aParent ) wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); EDA_DRAW_PANEL_GAL::GAL_TYPE backend = m_parent->GetCanvas()->GetBackend(); - m_symbol_preview = new SYMBOL_PREVIEW_WIDGET( panel, &Kiway(), backend ); + m_symbol_preview = new SYMBOL_PREVIEW_WIDGET( panel, &Kiway(), true, backend ); m_symbol_preview->SetLayoutDirection( wxLayout_LeftToRight ); if( m_show_footprints ) diff --git a/eeschema/dialogs/dialog_rescue_each.cpp b/eeschema/dialogs/dialog_rescue_each.cpp index c7cfc2d8be..a96315ddfe 100644 --- a/eeschema/dialogs/dialog_rescue_each.cpp +++ b/eeschema/dialogs/dialog_rescue_each.cpp @@ -89,10 +89,12 @@ DIALOG_RESCUE_EACH::DIALOG_RESCUE_EACH( wxWindow* aParent, { wxASSERT( aCurrentSheet ); - m_previewOldWidget = new SYMBOL_PREVIEW_WIDGET( m_previewOldPanel, &Kiway(), aGalBackEndType ); + m_previewOldWidget = new SYMBOL_PREVIEW_WIDGET( m_previewOldPanel, &Kiway(), false, + aGalBackEndType ); m_SizerOldPanel->Add( m_previewOldWidget, 1, wxEXPAND | wxALL, 5 ); - m_previewNewWidget = new SYMBOL_PREVIEW_WIDGET( m_previewNewPanel, &Kiway(), aGalBackEndType ); + m_previewNewWidget = new SYMBOL_PREVIEW_WIDGET( m_previewNewPanel, &Kiway(), false, + aGalBackEndType ); m_SizerNewPanel->Add( m_previewNewWidget, 1, wxEXPAND | wxALL, 5 ); // Set the info message, customized to include the proper suffix. diff --git a/eeschema/symbol_tree_synchronizing_adapter.cpp b/eeschema/symbol_tree_synchronizing_adapter.cpp index 46f51bc286..ab34d02c43 100644 --- a/eeschema/symbol_tree_synchronizing_adapter.cpp +++ b/eeschema/symbol_tree_synchronizing_adapter.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include wxObjectDataPtr @@ -357,3 +359,40 @@ bool SYMBOL_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, un return true; } + + +bool SYMBOL_TREE_SYNCHRONIZING_ADAPTER::HasPreview( const wxDataViewItem& aItem ) +{ + LIB_TREE_NODE* node = ToNode( aItem ); + wxCHECK( node, false ); + + return node->m_Type == LIB_TREE_NODE::LIBID; +} + + +void SYMBOL_TREE_SYNCHRONIZING_ADAPTER::ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem ) +{ + LIB_TREE_NODE* node = ToNode( aItem ); + wxCHECK( node, /* void */ ); + + wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL ); + aParent->SetSizer( mainSizer ); + + WX_PANEL* panel = new WX_PANEL( aParent ); + panel->SetBorders( true, true, true, true ); + panel->SetBorderColor( KIGFX::COLOR4D::BLACK ); + + wxBoxSizer* panelSizer = new wxBoxSizer( wxVERTICAL ); + panel->SetSizer( panelSizer ); + + EDA_DRAW_PANEL_GAL::GAL_TYPE backend = m_frame->GetCanvas()->GetBackend(); + SYMBOL_PREVIEW_WIDGET* preview = new SYMBOL_PREVIEW_WIDGET( panel, &m_frame->Kiway(), + false, backend ); + preview->SetLayoutDirection( wxLayout_LeftToRight ); + + panelSizer->Add( preview, 1, wxEXPAND|wxALL, 1 ); + mainSizer->Add( panel, 1, wxEXPAND, 0 ); + aParent->Layout(); + + preview->DisplaySymbol( node->m_LibId, node->m_Unit ); +} \ No newline at end of file diff --git a/eeschema/symbol_tree_synchronizing_adapter.h b/eeschema/symbol_tree_synchronizing_adapter.h index d79a035c2b..3ca7c08db4 100644 --- a/eeschema/symbol_tree_synchronizing_adapter.h +++ b/eeschema/symbol_tree_synchronizing_adapter.h @@ -50,6 +50,9 @@ public: wxDataViewItem GetCurrentDataViewItem() override; + virtual bool HasPreview( const wxDataViewItem& aItem ) override; + virtual void ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem ) override; + protected: void updateLibrary( LIB_TREE_NODE_LIB& aLibNode ); diff --git a/eeschema/widgets/symbol_diff_widget.cpp b/eeschema/widgets/symbol_diff_widget.cpp index 88f79b7eac..0ce3e845f2 100644 --- a/eeschema/widgets/symbol_diff_widget.cpp +++ b/eeschema/widgets/symbol_diff_widget.cpp @@ -29,7 +29,7 @@ SYMBOL_DIFF_WIDGET::SYMBOL_DIFF_WIDGET( wxWindow* aParent, EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) : - SYMBOL_PREVIEW_WIDGET( aParent, nullptr, aCanvasType ), + SYMBOL_PREVIEW_WIDGET( aParent, nullptr, false, aCanvasType ), m_libraryItem( nullptr ), m_slider( nullptr ) { diff --git a/eeschema/widgets/symbol_preview_widget.cpp b/eeschema/widgets/symbol_preview_widget.cpp index d7d2e95ac9..488cb5b14e 100644 --- a/eeschema/widgets/symbol_preview_widget.cpp +++ b/eeschema/widgets/symbol_preview_widget.cpp @@ -32,12 +32,13 @@ #include -SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY* aKiway, +SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY* aKiway, bool aIncludeStatus, EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) : wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ), m_kiway( aKiway ), m_preview( nullptr ), m_status( nullptr ), + m_statusPanel( nullptr ), m_statusSizer( nullptr ), m_previewItem( nullptr ) { @@ -84,30 +85,38 @@ SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY* aKiway, settings->m_ShowPinsElectricalType = app_settings->m_LibViewPanel.show_pin_electrical_type; settings->m_ShowPinNumbers = app_settings->m_LibViewPanel.show_pin_numbers; - m_statusPanel = new wxPanel( this ); - m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() ); - m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString ); - m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() ); - m_statusSizer = new wxBoxSizer( wxVERTICAL ); - m_statusSizer->Add( 0, 0, 1 ); // add a spacer - m_statusSizer->Add( m_status, 0, wxALIGN_CENTER ); - m_statusSizer->Add( 0, 0, 1 ); // add a spacer - m_statusPanel->SetSizer( m_statusSizer ); - - // Give the status panel the same color scheme as the canvas so it isn't jarring when - // switched to. - m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() ); - m_statusPanel->SetForegroundColour( foregroundColor.ToColour() ); - - // Give the preview panel a small top border to align its top with the status panel, - // and give the status panel a small bottom border to align its bottom with the preview - // panel. m_outerSizer = new wxBoxSizer( wxVERTICAL ); - m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 ); - m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 ); - // Hide the status panel to start - m_statusPanel->Hide(); + if( aIncludeStatus ) + { + m_statusPanel = new wxPanel( this ); + m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() ); + m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString ); + m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() ); + m_statusSizer = new wxBoxSizer( wxVERTICAL ); + m_statusSizer->Add( 0, 0, 1 ); // add a spacer + m_statusSizer->Add( m_status, 0, wxALIGN_CENTER ); + m_statusSizer->Add( 0, 0, 1 ); // add a spacer + m_statusPanel->SetSizer( m_statusSizer ); + + // Give the status panel the same color scheme as the canvas so it isn't jarring when + // switched to. + m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() ); + m_statusPanel->SetForegroundColour( foregroundColor.ToColour() ); + + // Give the preview panel a small top border to align its top with the status panel, + // and give the status panel a small bottom border to align its bottom with the preview + // panel. + m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 ); + m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 ); + + // Hide the status panel to start + m_statusPanel->Hide(); + } + else + { + m_outerSizer->Add( m_preview, 1, wxEXPAND, 0 ); + } SetSizer( m_outerSizer ); Layout(); @@ -127,6 +136,8 @@ SYMBOL_PREVIEW_WIDGET::~SYMBOL_PREVIEW_WIDGET() void SYMBOL_PREVIEW_WIDGET::SetStatusText( wxString const& aText ) { + wxCHECK( m_statusPanel, /* void */ ); + m_status->SetLabel( aText ); m_preview->Hide(); m_statusPanel->Show(); @@ -232,7 +243,10 @@ void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, i if( !m_preview->IsShown() ) { m_preview->Show(); - m_statusPanel->Hide(); + + if( m_statusPanel ) + m_statusPanel->Hide(); + Layout(); // Ensure panel size is up to date. } @@ -281,6 +295,9 @@ void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_SYMBOL* aSymbol, int aUnit, int aCo m_preview->ForceRefresh(); m_preview->Show(); - m_statusPanel->Hide(); + + if( m_statusPanel ) + m_statusPanel->Hide(); + Layout(); } diff --git a/eeschema/widgets/symbol_preview_widget.h b/eeschema/widgets/symbol_preview_widget.h index e5c99b350d..69b25e9b85 100644 --- a/eeschema/widgets/symbol_preview_widget.h +++ b/eeschema/widgets/symbol_preview_widget.h @@ -43,7 +43,7 @@ public: * @param aKiway - an active Kiway instance * @param aCanvasType = the type of canvas (GAL_TYPE_OPENGL or GAL_TYPE_CAIRO only) */ - SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY* aKiway, + SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY* aKiway, bool aIncludeStatus, EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ); ~SYMBOL_PREVIEW_WIDGET() override; diff --git a/include/lib_tree_model_adapter.h b/include/lib_tree_model_adapter.h index a59dc70c96..f434e1c361 100644 --- a/include/lib_tree_model_adapter.h +++ b/include/lib_tree_model_adapter.h @@ -259,7 +259,10 @@ public: LIB_TREE_NODE* GetTreeNodeFor( const wxDataViewItem& aSelection ) const; - virtual wxString GenerateInfo( const LIB_ID& aLibId, int aUnit ) { return wxEmptyString; }; + virtual wxString GenerateInfo( const LIB_ID& aLibId, int aUnit ) { return wxEmptyString; } + + virtual bool HasPreview( const wxDataViewItem& aItem ) { return false; } + virtual void ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem ) {} /** * Return the number of symbols loaded in the tree. diff --git a/include/widgets/lib_tree.h b/include/widgets/lib_tree.h index 96abdba97e..677b37c171 100644 --- a/include/widgets/lib_tree.h +++ b/include/widgets/lib_tree.h @@ -26,6 +26,7 @@ #define LIB_TREE_H #include +#include #include #include #include @@ -35,6 +36,7 @@ class wxHtmlLinkEvent; class wxSearchCtrl; class wxTimer; class wxTimerEvent; +class wxPopupWindow; class STD_BITMAP_BUTTON; class ACTION_MENU; class LIB_ID; @@ -204,6 +206,9 @@ protected: void updateRecentSearchMenu(); + void showPreview( wxDataViewItem aItem ); + void hidePreview(); + void onQueryText( wxCommandEvent& aEvent ); void onQueryCharHook( wxKeyEvent& aEvent ); void onQueryMouseMoved( wxMouseEvent& aEvent ); @@ -212,6 +217,9 @@ protected: void onTreeActivate( wxDataViewEvent& aEvent ); void onTreeCharHook( wxKeyEvent& aEvent ); + void onIdle( wxIdleEvent& aEvent ); + void onHoverTimer( wxTimerEvent& aEvent ); + void onDetailsLink( wxHtmlLinkEvent& aEvent ); void onPreselect( wxCommandEvent& aEvent ); void onItemContextMenu( wxDataViewEvent& aEvent ); @@ -232,6 +240,11 @@ protected: wxString m_recentSearchesKey; bool m_skipNextRightClick; + + wxPoint m_hoverPos; + wxDataViewItem m_hoverItem; + wxTimer m_hoverTimer; + wxPopupWindow* m_previewWindow; }; ///< Custom event sent when a new symbol is preselected diff --git a/include/widgets/wx_panel.h b/include/widgets/wx_panel.h index e429c07042..312a313f36 100644 --- a/include/widgets/wx_panel.h +++ b/include/widgets/wx_panel.h @@ -25,6 +25,7 @@ #define WX_PANEL_H #include +#include class WX_PANEL : public wxPanel { @@ -43,6 +44,11 @@ public: m_bottomBorder = aBottom; } + void SetBorderColor( const KIGFX::COLOR4D& aColor ) + { + m_borderColor = aColor; + } + private: void OnPaint( wxPaintEvent& event ); @@ -51,6 +57,8 @@ private: bool m_rightBorder; bool m_topBorder; bool m_bottomBorder; + + KIGFX::COLOR4D m_borderColor; }; diff --git a/pcbnew/dialogs/panel_pcbnew_color_settings.cpp b/pcbnew/dialogs/panel_pcbnew_color_settings.cpp index cfe842f4cc..f2da226537 100644 --- a/pcbnew/dialogs/panel_pcbnew_color_settings.cpp +++ b/pcbnew/dialogs/panel_pcbnew_color_settings.cpp @@ -673,12 +673,13 @@ std::set g_excludedLayers = }; -PANEL_PCBNEW_COLOR_SETTINGS::PANEL_PCBNEW_COLOR_SETTINGS( wxWindow* aParent, BOARD* aBoard ) - : PANEL_COLOR_SETTINGS( aParent ), - m_preview( nullptr ), - m_page( nullptr ), - m_titleBlock( nullptr ), - m_board( aBoard ) +PANEL_PCBNEW_COLOR_SETTINGS::PANEL_PCBNEW_COLOR_SETTINGS( wxWindow* aParent, BOARD* aBoard ) : + PANEL_COLOR_SETTINGS( aParent ), + UNITS_PROVIDER( pcbIUScale, EDA_UNITS::MILLIMETRES ), + m_preview( nullptr ), + m_page( nullptr ), + m_titleBlock( nullptr ), + m_board( aBoard ) { m_colorNamespace = "board"; @@ -762,7 +763,7 @@ void PANEL_PCBNEW_COLOR_SETTINGS::createSwatches() createSwatch( layer, name ); } - m_preview = FOOTPRINT_PREVIEW_PANEL::New( nullptr, m_panel1 ); + m_preview = FOOTPRINT_PREVIEW_PANEL::New( nullptr, m_panel1, this ); m_preview->GetGAL()->SetAxesEnabled( false ); m_previewPanelSizer->Add( m_preview, 1, wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/panel_pcbnew_color_settings.h b/pcbnew/dialogs/panel_pcbnew_color_settings.h index fa3b157222..af144033f0 100644 --- a/pcbnew/dialogs/panel_pcbnew_color_settings.h +++ b/pcbnew/dialogs/panel_pcbnew_color_settings.h @@ -22,13 +22,14 @@ #define PANEL_PCBNEW_COLOR_SETTINGS_H_ #include +#include class PAGE_INFO; class FOOTPRINT_PREVIEW_PANEL; class TITLE_BLOCK; -class PANEL_PCBNEW_COLOR_SETTINGS : public PANEL_COLOR_SETTINGS +class PANEL_PCBNEW_COLOR_SETTINGS : public PANEL_COLOR_SETTINGS, public UNITS_PROVIDER { public: PANEL_PCBNEW_COLOR_SETTINGS( wxWindow* aParent, BOARD* aBoard ); diff --git a/pcbnew/footprint_preview_panel.cpp b/pcbnew/footprint_preview_panel.cpp index fa7b531cee..19f6d3d4cb 100644 --- a/pcbnew/footprint_preview_panel.cpp +++ b/pcbnew/footprint_preview_panel.cpp @@ -44,6 +44,7 @@ #include FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aParent, + UNITS_PROVIDER* aUnitsProvider, std::unique_ptr aOpts, GAL_TYPE aGalType ) : PCB_DRAW_PANEL_GAL( aParent, -1, wxPoint( 0, 0 ), wxSize( 200, 200 ), *aOpts, aGalType ), @@ -55,18 +56,7 @@ FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aPare ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER ); EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas - wxWindow* topLevelParent = aParent; - - while( topLevelParent && !topLevelParent->IsTopLevel() ) - topLevelParent = topLevelParent->GetParent(); - - if( topLevelParent ) - { - if( DIALOG_SHIM* parentDlg = dynamic_cast( topLevelParent ) ) - m_userUnits = parentDlg->GetUserUnits(); - else if( UNITS_PROVIDER* parentFrame = dynamic_cast( topLevelParent ) ) - m_userUnits = parentFrame->GetUserUnits(); - } + m_userUnits = aUnitsProvider->GetUserUnits(); m_dummyBoard = std::make_unique(); m_dummyBoard->SetUserUnits( m_userUnits ); @@ -245,7 +235,8 @@ wxWindow* FOOTPRINT_PREVIEW_PANEL::GetWindow() } -FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* aParent ) +FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* aParent, + UNITS_PROVIDER* aUnitsProvider ) { PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings(); @@ -267,8 +258,9 @@ FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* gal_opts = std::make_unique(); gal_opts->ReadConfig( *Pgm().GetCommonSettings(), cfg->m_Window, aParent ); - auto canvasType = static_cast( cfg->m_Graphics.canvas_type ); - auto panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, std::move( gal_opts ), canvasType ); + auto galType = static_cast( cfg->m_Graphics.canvas_type ); + FOOTPRINT_PREVIEW_PANEL* panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, aUnitsProvider, + std::move( gal_opts ), galType ); panel->UpdateColors(); diff --git a/pcbnew/footprint_preview_panel.h b/pcbnew/footprint_preview_panel.h index b654b985a1..ecf21030ce 100644 --- a/pcbnew/footprint_preview_panel.h +++ b/pcbnew/footprint_preview_panel.h @@ -66,7 +66,8 @@ public: virtual void RefreshAll() override; - static FOOTPRINT_PREVIEW_PANEL* New( KIWAY* aKiway, wxWindow* aParent ); + static FOOTPRINT_PREVIEW_PANEL* New( KIWAY* aKiway, wxWindow* aParent, + UNITS_PROVIDER* aUnitsProvider ); private: /** @@ -77,9 +78,8 @@ private: * @param aOpts the GAL options (ownership is assumed) * @param aGalType the displayed GAL type */ - FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aParent, - std::unique_ptr aOpts, - GAL_TYPE aGalType ); + FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aParent, UNITS_PROVIDER* aUnitsProvider, + std::unique_ptr aOpts, GAL_TYPE aGalType ); void renderFootprint( std::shared_ptr aFootprint ); diff --git a/pcbnew/fp_tree_synchronizing_adapter.cpp b/pcbnew/fp_tree_synchronizing_adapter.cpp index 990e3c5a22..e495802ceb 100644 --- a/pcbnew/fp_tree_synchronizing_adapter.cpp +++ b/pcbnew/fp_tree_synchronizing_adapter.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -304,3 +305,29 @@ bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsign } +bool FP_TREE_SYNCHRONIZING_ADAPTER::HasPreview( const wxDataViewItem& aItem ) +{ + LIB_TREE_NODE* node = ToNode( aItem ); + wxCHECK( node, false ); + + return node->m_Type == LIB_TREE_NODE::LIBID; +} + + +void FP_TREE_SYNCHRONIZING_ADAPTER::ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem ) +{ + LIB_TREE_NODE* node = ToNode( aItem ); + wxCHECK( node, /* void */ ); + + wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL ); + aParent->SetSizer( mainSizer ); + + FOOTPRINT_PREVIEW_PANEL* preview = FOOTPRINT_PREVIEW_PANEL::New( &m_frame->Kiway(), aParent, + m_frame ); + preview->GetGAL()->SetAxesEnabled( false ); + + mainSizer->Add( preview, 1, wxEXPAND|wxALL, 1 ); + aParent->Layout(); + + preview->DisplayFootprint( node->m_LibId ); +} \ No newline at end of file diff --git a/pcbnew/fp_tree_synchronizing_adapter.h b/pcbnew/fp_tree_synchronizing_adapter.h index e369841b0e..72093ea077 100644 --- a/pcbnew/fp_tree_synchronizing_adapter.h +++ b/pcbnew/fp_tree_synchronizing_adapter.h @@ -46,6 +46,9 @@ public: wxDataViewItem GetCurrentDataViewItem() override; + virtual bool HasPreview( const wxDataViewItem& aItem ) override; + virtual void ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem ) override; + protected: FP_TREE_SYNCHRONIZING_ADAPTER( FOOTPRINT_EDIT_FRAME* aFrame, FP_LIB_TABLE* aLibs ); diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index f3977106af..3602414e39 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -119,7 +119,7 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) ); case FRAME_FOOTPRINT_PREVIEW: - return dynamic_cast< wxWindow* >( FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent ) ); + return FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent, this ); case DIALOG_CONFIGUREPATHS: {