summaryrefslogtreecommitdiff
path: root/eeschema/viewlib_frame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'eeschema/viewlib_frame.cpp')
-rw-r--r--eeschema/viewlib_frame.cpp595
1 files changed, 595 insertions, 0 deletions
diff --git a/eeschema/viewlib_frame.cpp b/eeschema/viewlib_frame.cpp
new file mode 100644
index 0000000..ddcefa9
--- /dev/null
+++ b/eeschema/viewlib_frame.cpp
@@ -0,0 +1,595 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file viewlib_frame.cpp
+ */
+
+#include <fctsys.h>
+#include <kiface_i.h>
+#include <pgm_base.h>
+#include <eeschema_id.h>
+#include <class_drawpanel.h>
+#include <schframe.h>
+#include <msgpanel.h>
+
+#include <general.h>
+#include <viewlib_frame.h>
+#include <class_library.h>
+#include <hotkeys.h>
+#include <dialog_helpers.h>
+
+
+// Save previous component library viewer state.
+wxString LIB_VIEW_FRAME::m_libraryName;
+wxString LIB_VIEW_FRAME::m_entryName;
+
+int LIB_VIEW_FRAME::m_unit = 1;
+int LIB_VIEW_FRAME::m_convert = 1;
+
+
+BEGIN_EVENT_TABLE( LIB_VIEW_FRAME, EDA_DRAW_FRAME )
+ // Window events
+ EVT_CLOSE( LIB_VIEW_FRAME::OnCloseWindow )
+ EVT_SIZE( LIB_VIEW_FRAME::OnSize )
+ EVT_ACTIVATE( LIB_VIEW_FRAME::OnActivate )
+
+ // Toolbar events
+ EVT_TOOL_RANGE( ID_LIBVIEW_NEXT, ID_LIBVIEW_DE_MORGAN_CONVERT_BUTT,
+ LIB_VIEW_FRAME::Process_Special_Functions )
+
+ EVT_TOOL( ID_LIBVIEW_CMP_EXPORT_TO_SCHEMATIC, LIB_VIEW_FRAME::ExportToSchematicLibraryPart )
+ EVT_COMBOBOX( ID_LIBVIEW_SELECT_PART_NUMBER, LIB_VIEW_FRAME::Process_Special_Functions )
+
+ // listbox events
+ EVT_LISTBOX( ID_LIBVIEW_LIB_LIST, LIB_VIEW_FRAME::ClickOnLibList )
+ EVT_LISTBOX( ID_LIBVIEW_CMP_LIST, LIB_VIEW_FRAME::ClickOnCmpList )
+ EVT_LISTBOX_DCLICK( ID_LIBVIEW_CMP_LIST, LIB_VIEW_FRAME::DClickOnCmpList )
+
+ // Menu (and/or hotkey) events
+ EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp )
+ EVT_MENU( wxID_EXIT, LIB_VIEW_FRAME::CloseLibraryViewer )
+ EVT_MENU( ID_SET_RELATIVE_OFFSET, LIB_VIEW_FRAME::OnSetRelativeOffset )
+
+END_EVENT_TABLE()
+
+
+/* Note:
+ * LIB_VIEW_FRAME can be build in "modal mode", or as a usual frame.
+ * In modal mode:
+ * a tool to export the selected symbol is shown in the toolbar
+ * the style is wxSTAY_ON_TOP on Windows and wxFRAME_FLOAT_ON_PARENT on unix
+ * reason:
+ * the parent is usually the kicad window manager (not easy to change)
+ * On windows, when the frame with stype wxFRAME_FLOAT_ON_PARENT is displayed
+ * its parent frame is brought to the foreground, on the top of the calling frame.
+ * and stays displayed when closing the LIB_VIEW_FRAME frame.
+ * this issue does not happen on unix.
+ *
+ * So we use wxSTAY_ON_TOP on Windows, and wxFRAME_FLOAT_ON_PARENT on unix
+ * to simulate a dialog called by ShowModal.
+ */
+
+#define LIB_VIEW_FRAME_NAME wxT( "ViewlibFrame" )
+
+LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
+ PART_LIB* aLibrary ) :
+ SCH_BASE_FRAME( aKiway, aParent, aFrameType, _( "Library Browser" ),
+ wxDefaultPosition, wxDefaultSize,
+ aFrameType==FRAME_SCH_VIEWER_MODAL ?
+#ifdef __WINDOWS__
+ KICAD_DEFAULT_DRAWFRAME_STYLE | wxSTAY_ON_TOP :
+#else
+ KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT :
+#endif
+ KICAD_DEFAULT_DRAWFRAME_STYLE,
+ LIB_VIEW_FRAME_NAME )
+{
+ wxASSERT( aFrameType == FRAME_SCH_VIEWER || aFrameType == FRAME_SCH_VIEWER_MODAL );
+
+ if( aFrameType == FRAME_SCH_VIEWER_MODAL )
+ SetModal( true );
+
+ m_configFrameName = LIB_VIEW_FRAME_NAME;
+
+ // Give an icon
+ wxIcon icon;
+ icon.CopyFromBitmap( KiBitmap( library_browse_xpm ) );
+ SetIcon( icon );
+
+ m_hotkeysDescrList = g_Viewlib_Hokeys_Descr;
+ m_cmpList = NULL;
+ m_libList = NULL;
+ m_listPowerCmpOnly = false;
+
+ SetScreen( new SCH_SCREEN( aKiway ) );
+ GetScreen()->m_Center = true; // Axis origin centered on screen.
+ LoadSettings( config() );
+
+ SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
+
+ // Initialize grid id to the default value (50 mils):
+ m_LastGridSizeId = ID_POPUP_GRID_LEVEL_50 - ID_POPUP_GRID_LEVEL_1000;
+ GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
+
+ // Menu bar is not mandatory: uncomment/comment the next line
+ // to add/remove the menubar
+ ReCreateMenuBar();
+ ReCreateHToolbar();
+ ReCreateVToolbar();
+
+ if( !aLibrary )
+ {
+ // Creates the libraries window display
+ m_libList = new wxListBox( this, ID_LIBVIEW_LIB_LIST,
+ wxPoint( 0, 0 ), wxSize(m_libListWidth, -1),
+ 0, NULL, wxLB_HSCROLL );
+ }
+ else
+ {
+ m_libraryName = aLibrary->GetName();
+ m_entryName.Clear();
+ m_unit = 1;
+ m_convert = 1;
+ m_libListWidth = 0;
+ }
+
+ // Creates the component window display
+ m_cmpList = new wxListBox( this, ID_LIBVIEW_CMP_LIST,
+ wxPoint( 0, 0 ), wxSize(m_cmpListWidth, -1),
+ 0, NULL, wxLB_HSCROLL );
+
+ if( m_libList )
+ ReCreateListLib();
+
+ DisplayLibInfos();
+
+ m_auimgr.SetManagedWindow( this );
+
+ EDA_PANEINFO horiz;
+ horiz.HorizontalToolbarPane();
+
+ EDA_PANEINFO vert;
+ vert.VerticalToolbarPane();
+
+ EDA_PANEINFO info;
+ info.InfoToolbarPane();
+
+ EDA_PANEINFO mesg;
+ mesg.MessageToolbarPane();
+
+
+ // Manage main toolbal
+ m_auimgr.AddPane( m_mainToolBar,
+ wxAuiPaneInfo( horiz ).Name( wxT ("m_mainToolBar" ) ).Top().Row( 0 ) );
+
+ // Manage the left window (list of libraries)
+ if( m_libList )
+ m_auimgr.AddPane( m_libList, wxAuiPaneInfo( info ).Name( wxT( "m_libList" ) ).
+ Left().Row( 0 ) );
+
+ // Manage the list of components)
+ m_auimgr.AddPane( m_cmpList,
+ wxAuiPaneInfo( info ).Name( wxT( "m_cmpList" ) ).
+ Left().Row( 1 ) );
+
+ // Manage the draw panel
+ m_auimgr.AddPane( m_canvas,
+ wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() );
+
+ // Manage the message panel
+ m_auimgr.AddPane( m_messagePanel,
+ wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) );
+
+ /* Now the minimum windows are fixed, set library list
+ * and component list of the previous values from last viewlib use
+ */
+ if( m_libList )
+ {
+ m_auimgr.GetPane( m_libList ).MinSize( wxSize( 80, -1) );
+ m_auimgr.GetPane( m_libList ).BestSize( wxSize(m_libListWidth, -1) );
+ }
+
+ m_auimgr.GetPane( m_cmpList ).MinSize( wxSize( 80, -1) );
+ m_auimgr.GetPane( m_cmpList ).BestSize(wxSize(m_cmpListWidth, -1) );
+
+ m_auimgr.Update();
+
+ // Now Drawpanel is sized, we can use BestZoom to show the component (if any)
+#ifdef USE_WX_GRAPHICS_CONTEXT
+ GetScreen()->SetZoom( BestZoom() );
+#else
+ Zoom_Automatique( false );
+#endif
+
+ if( !IsModal() ) // For modal mode, calling ShowModal() will show this frame
+ {
+ Raise();
+ Show( true );
+ }
+}
+
+
+LIB_VIEW_FRAME::~LIB_VIEW_FRAME()
+{
+}
+
+
+void LIB_VIEW_FRAME::OnCloseWindow( wxCloseEvent& Event )
+{
+ if( !IsModal() )
+ {
+ Destroy();
+ }
+ else if( !IsDismissed() )
+ {
+ // only dismiss modal frame if not already dismissed.
+ DismissModal( false );
+
+ // Modal frame will be destroyed by the calling function.
+ }
+}
+
+
+void LIB_VIEW_FRAME::OnSize( wxSizeEvent& SizeEv )
+{
+ if( m_auimgr.GetManagedWindow() )
+ m_auimgr.Update();
+
+ SizeEv.Skip();
+}
+
+
+void LIB_VIEW_FRAME::OnSetRelativeOffset( wxCommandEvent& event )
+{
+ GetScreen()->m_O_Curseur = GetCrossHairPosition();
+ UpdateStatusBar();
+}
+
+
+double LIB_VIEW_FRAME::BestZoom()
+{
+ /* Please, note: wxMSW before version 2.9 seems have
+ * problems with zoom values < 1 ( i.e. userscale > 1) and needs to be patched:
+ * edit file <wxWidgets>/src/msw/dc.cpp
+ * search for line static const int VIEWPORT_EXTENT = 1000;
+ * and replace by static const int VIEWPORT_EXTENT = 10000;
+ */
+
+ LIB_PART* part = NULL;
+ double bestzoom = 16.0; // default value for bestzoom
+ PART_LIB* lib = Prj().SchLibs()->FindLibrary( m_libraryName );
+
+ if( lib )
+ part = lib->FindPart( m_entryName );
+
+ if( !part )
+ {
+ SetScrollCenterPosition( wxPoint( 0, 0 ) );
+ return bestzoom;
+ }
+
+ wxSize size = m_canvas->GetClientSize();
+
+ EDA_RECT boundingBox = part->GetBoundingBox( m_unit, m_convert );
+
+ // Reserve a 10% margin around component bounding box.
+ double margin_scale_factor = 0.8;
+ double zx =(double) boundingBox.GetWidth() /
+ ( margin_scale_factor * (double)size.x );
+ double zy = (double) boundingBox.GetHeight() /
+ ( margin_scale_factor * (double)size.y);
+
+ // Calculates the best zoom
+ bestzoom = std::max( zx, zy );
+
+ // keep it >= minimal existing zoom (can happen for very small components
+ // like small power symbols
+ if( bestzoom < GetScreen()->m_ZoomList[0] )
+ bestzoom = GetScreen()->m_ZoomList[0];
+
+ SetScrollCenterPosition( boundingBox.Centre() );
+
+ return bestzoom;
+}
+
+
+void LIB_VIEW_FRAME::ReCreateListLib()
+{
+ if( !m_libList )
+ return;
+
+ m_libList->Clear();
+
+ wxArrayString libs = Prj().SchLibs()->GetLibraryNames();
+
+ // Remove not allowed libs from main list, if the allowed lib list is not empty
+ if( m_allowedLibs.GetCount() )
+ {
+ for( unsigned ii = 0; ii < libs.GetCount(); )
+ {
+ if( m_allowedLibs.Index( libs[ii] ) == wxNOT_FOUND )
+ libs.RemoveAt( ii );
+ else
+ ii++;
+ }
+ }
+
+ // Remove libs which have no power components, if this filter is activated
+ if( m_listPowerCmpOnly )
+ {
+ for( unsigned ii = 0; ii < libs.GetCount(); )
+ {
+ PART_LIB* lib = Prj().SchLibs()->FindLibrary( libs[ii] );
+
+ if( lib && !lib->HasPowerParts() )
+ libs.RemoveAt( ii );
+ else
+ ii++;
+ }
+ }
+
+ m_libList->Append( libs );
+
+ // Search for a previous selection:
+ int index = m_libList->FindString( m_libraryName );
+
+ if( index != wxNOT_FOUND )
+ {
+ m_libList->SetSelection( index, true );
+ }
+ else
+ {
+ // If not found, clear current library selection because it can be
+ // deleted after a config change.
+ m_libraryName = wxEmptyString;
+ m_entryName = wxEmptyString;
+ m_unit = 1;
+ m_convert = 1;
+ }
+
+ ReCreateListCmp();
+ ReCreateHToolbar();
+ DisplayLibInfos();
+ m_canvas->Refresh();
+}
+
+
+void LIB_VIEW_FRAME::ReCreateListCmp()
+{
+ if( m_cmpList == NULL )
+ return;
+
+ m_cmpList->Clear();
+
+ PART_LIB* lib = Prj().SchLibs()->FindLibrary( m_libraryName );
+
+ if( !lib )
+ {
+ m_libraryName = wxEmptyString;
+ m_entryName = wxEmptyString;
+ m_convert = 1;
+ m_unit = 1;
+ return;
+ }
+
+ wxArrayString nameList;
+
+ if( m_listPowerCmpOnly )
+ lib->GetEntryTypePowerNames( nameList );
+ else
+ lib->GetEntryNames( nameList );
+
+ m_cmpList->Append( nameList );
+
+ int index = m_cmpList->FindString( m_entryName );
+
+ if( index == wxNOT_FOUND )
+ {
+ m_entryName = wxEmptyString;
+ m_convert = 1;
+ m_unit = 1;
+ }
+ else
+ {
+ m_cmpList->SetSelection( index, true );
+ }
+}
+
+
+void LIB_VIEW_FRAME::ClickOnLibList( wxCommandEvent& event )
+{
+ int ii = m_libList->GetSelection();
+
+ if( ii < 0 )
+ return;
+
+ SetSelectedLibrary( m_libList->GetString( ii ) );
+}
+
+
+void LIB_VIEW_FRAME::SetSelectedLibrary( const wxString& aLibraryName )
+{
+ if( m_libraryName == aLibraryName )
+ return;
+
+ m_libraryName = aLibraryName;
+ ReCreateListCmp();
+ m_canvas->Refresh();
+ DisplayLibInfos();
+ ReCreateHToolbar();
+
+ // Ensure the corresponding line in m_libList is selected
+ // (which is not necessary the case if SetSelectedLibrary is called
+ // by an other caller than ClickOnLibList.
+ m_libList->SetStringSelection( m_libraryName, true );
+}
+
+
+void LIB_VIEW_FRAME::ClickOnCmpList( wxCommandEvent& event )
+{
+ int ii = m_cmpList->GetSelection();
+
+ if( ii < 0 )
+ return;
+
+ SetSelectedComponent( m_cmpList->GetString( ii ) );
+}
+
+
+void LIB_VIEW_FRAME::SetSelectedComponent( const wxString& aComponentName )
+{
+ if( m_entryName.CmpNoCase( aComponentName ) != 0 )
+ {
+ m_entryName = aComponentName;
+
+ // Ensure the corresponding line in m_cmpList is selected
+ // (which is not necessarily the case if SetSelectedComponent is called
+ // by another caller than ClickOnCmpList.
+ m_cmpList->SetStringSelection( aComponentName, true );
+ DisplayLibInfos();
+ m_unit = 1;
+ m_convert = 1;
+ Zoom_Automatique( false );
+ ReCreateHToolbar();
+ m_canvas->Refresh();
+ }
+}
+
+
+void LIB_VIEW_FRAME::DClickOnCmpList( wxCommandEvent& event )
+{
+ if( IsModal() )
+ {
+ ExportToSchematicLibraryPart( event );
+
+ // The schematic editor might not be the parent of the library viewer.
+ // It could be a python window.
+ SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
+
+ if( schframe )
+ {
+ // Prevent the double click from being as a single click in the parent
+ // window which would cause the part to be parked rather than staying
+ // in drag mode.
+ schframe->SkipNextLeftButtonReleaseEvent();
+ }
+ }
+}
+
+
+void LIB_VIEW_FRAME::ExportToSchematicLibraryPart( wxCommandEvent& event )
+{
+ int ii = m_cmpList->GetSelection();
+
+ if( ii >= 0 )
+ {
+ wxString part_name = m_cmpList->GetString( ii );
+
+ // a selection was made, pass true
+ DismissModal( true, part_name );
+ }
+ else
+ {
+ // no selection was made, pass false
+ DismissModal( false );
+ }
+
+ Close( true );
+}
+
+
+#define LIBLIST_WIDTH_KEY wxT( "ViewLiblistWidth" )
+#define CMPLIST_WIDTH_KEY wxT( "ViewCmplistWidth" )
+
+// Currently, the library viewer has no dialog to change the background color
+// of the draw canvas. Therefore the background color is here just
+// in case of this option is added to some library viewer config dialog
+#define LIBVIEW_BGCOLOR wxT( "LibviewBgColor" )
+
+
+void LIB_VIEW_FRAME::LoadSettings( wxConfigBase* aCfg )
+{
+ EDA_DRAW_FRAME::LoadSettings( aCfg );
+
+ SetGridColor( GetLayerColor( LAYER_GRID ) );
+ SetDrawBgColor( GetLayerColor( LAYER_BACKGROUND ) );
+
+ aCfg->Read( LIBLIST_WIDTH_KEY, &m_libListWidth, 150 );
+ aCfg->Read( CMPLIST_WIDTH_KEY, &m_cmpListWidth, 150 );
+
+ // Set parameters to a reasonable value.
+ if( m_libListWidth > m_FrameSize.x/2 )
+ m_libListWidth = m_FrameSize.x/2;
+
+ if( m_cmpListWidth > m_FrameSize.x/2 )
+ m_cmpListWidth = m_FrameSize.x/2;
+}
+
+
+void LIB_VIEW_FRAME::SaveSettings( wxConfigBase* aCfg )
+{
+ EDA_DRAW_FRAME::SaveSettings( aCfg );
+
+ if( m_libListWidth && m_libList )
+ {
+ m_libListWidth = m_libList->GetSize().x;
+ aCfg->Write( LIBLIST_WIDTH_KEY, m_libListWidth );
+ }
+
+ m_cmpListWidth = m_cmpList->GetSize().x;
+ aCfg->Write( CMPLIST_WIDTH_KEY, m_cmpListWidth );
+}
+
+
+void LIB_VIEW_FRAME::OnActivate( wxActivateEvent& event )
+{
+ EDA_DRAW_FRAME::OnActivate( event );
+
+ if( m_libList )
+ ReCreateListLib();
+
+ DisplayLibInfos();
+}
+
+
+void LIB_VIEW_FRAME::CloseLibraryViewer( wxCommandEvent& event )
+{
+ Close();
+}
+
+void LIB_VIEW_FRAME::SetFilter( const SCHLIB_FILTER* aFilter )
+{
+ m_listPowerCmpOnly = false;
+ m_allowedLibs.Clear();
+
+ if( aFilter )
+ {
+ m_allowedLibs = aFilter->GetAllowedLibList();
+ m_listPowerCmpOnly = aFilter->GetFilterPowerParts();
+ }
+
+ ReCreateListLib();
+}