diff options
Diffstat (limited to 'kicad')
29 files changed, 6795 insertions, 0 deletions
diff --git a/kicad/CMakeLists.txt b/kicad/CMakeLists.txt new file mode 100644 index 0000000..f0e2438 --- /dev/null +++ b/kicad/CMakeLists.txt @@ -0,0 +1,148 @@ +add_definitions( -DKICAD ) + +include_directories( BEFORE ${INC_BEFORE} ) +include_directories( + ${INC_AFTER} + ) + + +set( KICAD_SRCS + class_treeprojectfiles.cpp + class_treeproject_item.cpp + commandframe.cpp + dialogs/dialog_template_selector_base.cpp + dialogs/dialog_template_selector.cpp + files-io.cpp + kicad.cpp + mainframe.cpp + menubar.cpp + preferences.cpp + prjconfig.cpp + project_template.cpp + tree_project_frame.cpp + ) + +if( MINGW ) + # KICAD_RESOURCES variable is set by the macro. + mingw_resource_compiler( kicad ) +else() + set( KICAD_RESOURCES kicad.rc ) +endif() + +if( APPLE ) + set( KICAD_RESOURCES kicad.icns kicad_doc.icns ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/kicad.icns" PROPERTIES + MACOSX_PACKAGE_LOCATION Resources + ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/kicad_doc.icns" PROPERTIES + MACOSX_PACKAGE_LOCATION Resources + ) + set( MACOSX_BUNDLE_ICON_FILE kicad.icns ) + set( MACOSX_BUNDLE_GUI_IDENTIFIER org.kicad-pcb.kicad ) + set( MACOSX_BUNDLE_NAME kicad ) +endif() + +add_executable( kicad WIN32 MACOSX_BUNDLE + ${KICAD_SRCS} + ${KICAD_EXTRA_SRCS} + ${KICAD_RESOURCES} + ) + +if( UNIX ) + # for build directory: create kiface symlinks so kicad (exe) can be run in-situ + add_custom_target( kiface_sym_links + COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_BINARY_DIR}/eeschema/_eeschema.kiface" "${CMAKE_BINARY_DIR}/kicad/_eeschema.kiface" + COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_BINARY_DIR}/pcbnew/_pcbnew.kiface" "${CMAKE_BINARY_DIR}/kicad/_pcbnew.kiface" + COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_BINARY_DIR}/cvpcb/_cvpcb.kiface" "${CMAKE_BINARY_DIR}/kicad/_cvpcb.kiface" + COMMENT "Making <build-dir>/kicad/<kiface.symlinks>" + ) +endif() + +if( APPLE ) + set_target_properties( kicad PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + ) + target_link_libraries( kicad + common + bitmaps + polygon + ${wxWidgets_LIBRARIES} + ) +else() + target_link_libraries( kicad + common + bitmaps + polygon + ${wxWidgets_LIBRARIES} + ${GDI_PLUS_LIBRARIES} + ) +endif() + +install( TARGETS kicad + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) +if( APPLE ) + # "install( CODE ... )" will launch its own CMake, so no variables from + # this CMake instance are accessible... use helper to transfer + if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) + set( SCRIPTING_HELPER "1" ) + else() + set( SCRIPTING_HELPER "0" ) + endif() + + # make main bundle relocatable + install( CODE " + # find all libs and modules + file( GLOB BUNDLE_FIX_LIBS ${OSX_BUNDLE_INSTALL_KIFACE_DIR}/*.kiface ) + if( ${SCRIPTING_HELPER} ) + file( GLOB WXPYTHON_DIR RELATIVE ${OSX_BUNDLE_INSTALL_LIB_DIR}/${PYTHON_LIB_DIR} ${OSX_BUNDLE_INSTALL_LIB_DIR}/${PYTHON_LIB_DIR}/wx-?.?-osx_cocoa ) + file( GLOB PYTHON_SCRIPTING_SO ${OSX_BUNDLE_INSTALL_LIB_DIR}/${PYTHON_LIB_DIR}/*.so ) + set( BUNDLE_FIX_LIBS \${BUNDLE_FIX_LIBS} \${PYTHON_SCRIPTING_SO} ) + file( GLOB PYTHON_SCRIPTING_SO ${OSX_BUNDLE_INSTALL_LIB_DIR}/${PYTHON_LIB_DIR}/\${WXPYTHON_DIR}/wx/*.so ) + set( BUNDLE_FIX_LIBS \${BUNDLE_FIX_LIBS} \${PYTHON_SCRIPTING_SO} ) + endif() + + # override default embedded path settings + ${OSX_BUNDLE_OVERRIDE_PATHS} + + # do all the work + include( BundleUtilities ) + + # If `BU_CHMOD_BUNDLE_ITEMS` is not set, `install_name_tool` will fail to re-write some loader paths due to lack of writable permissions if the build dependencies were installed by brew (or didn't have writable permissions) + set(BU_CHMOD_BUNDLE_ITEMS ON) + + fixup_bundle( ${OSX_BUNDLE_INSTALL_BIN_DIR}/kicad + \"\${BUNDLE_FIX_LIBS}\" + \"\" + ) + " COMPONENT Runtime + ) + + # move all individual app bundles into main bundle + install( CODE " + # helper function to move a bundle into main bundle + function( move_to_main_bundle bundle_name ) + message( STATUS \"Moving \${bundle_name} into main bundle...\" ) + file( MAKE_DIRECTORY ${OSX_BUNDLE_INSTALL_DIR}/${OSX_BUNDLE_APP_DIR} ) + file( REMOVE_RECURSE ${KICAD_BIN}/\${bundle_name}/${OSX_BUNDLE_LIB_DIR} ) + file( RENAME ${KICAD_BIN}/\${bundle_name} ${OSX_BUNDLE_INSTALL_DIR}/${OSX_BUNDLE_APP_DIR}/\${bundle_name} ) + execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink \"../../../Frameworks\" \"Frameworks\" + WORKING_DIRECTORY ${OSX_BUNDLE_INSTALL_DIR}/${OSX_BUNDLE_APP_DIR}/\${bundle_name}/Contents + ) + # create a top-level link pointing inside main bundle + execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink \"${OSX_BUNDLE_MAIN}/${OSX_BUNDLE_APP_DIR}/\${bundle_name}\" \"\${bundle_name}\" + WORKING_DIRECTORY ${KICAD_BIN} + ) + endfunction( move_to_main_bundle ) + + # move all app bundles + move_to_main_bundle( bitmap2component.app ) + move_to_main_bundle( eeschema.app ) + move_to_main_bundle( gerbview.app ) + move_to_main_bundle( pcb_calculator.app ) + move_to_main_bundle( pcbnew.app ) + move_to_main_bundle( pl_editor.app ) + " COMPONENT Runtime + ) +endif() diff --git a/kicad/Info.plist b/kicad/Info.plist new file mode 100644 index 0000000..9bb140d --- /dev/null +++ b/kicad/Info.plist @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeRole</key> <string>Editor</string> + <key>CFBundleTypeIconFile</key> <string>kicad_doc.icns</string> + <key>CFBundleTypeExtensions</key> <array> + <string>pro</string> + </array> + <key>CFBundleTypeName</key> <string>kicad project files</string> + <key>LSHandlerRank</key> <string>Owner</string> + </dict> + </array> + <key>CFBundleDevelopmentRegion</key> <string>English</string> + <key>CFBundleExecutable</key> <string>kicad</string> + <key>CFBundleGetInfoString</key> <string></string> + <key>CFBundleIconFile</key> <string>kicad.icns</string> + <key>CFBundleIdentifier</key> <string>org.kicad-pcb.kicad</string> + <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> + <key>CFBundleLongVersionString</key> <string></string> + <key>CFBundleName</key> <string>KiCad</string> + <key>CFBundlePackageType</key> <string>APPL</string> + <key>CFBundleShortVersionString</key> <string></string> + <key>CFBundleSignature</key> <string>????</string> + <key>CFBundleVersion</key> <string></string> + <key>CSResourcesFileMapped</key> <true/> + <key>LSRequiresCarbon</key> <true/> + <key>NSHumanReadableCopyright</key> <string></string> + <key>NSHighResolutionCapable</key> <string>True</string> +</dict> +</plist> diff --git a/kicad/class_treeproject_item.cpp b/kicad/class_treeproject_item.cpp new file mode 100644 index 0000000..56c5709 --- /dev/null +++ b/kicad/class_treeproject_item.cpp @@ -0,0 +1,262 @@ +/** + * @file class_treeproject_item.cpp + * + * @brief Class TREEPROJECT_ITEM is a derived class from wxTreeItemData and + * store info about a file or directory shown in the KiCad tree project files + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 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 + */ + + +#include <fctsys.h> +#include <gestfich.h> +#include <macros.h> + +#include <kicad.h> +#include <project.h> +#include <pgm_base.h> +#include <tree_project_frame.h> +#include <class_treeprojectfiles.h> +#include <class_treeproject_item.h> +#include <wx/imaglist.h> + +#include <wx/regex.h> +#include <wx/dir.h> + +TREEPROJECT_ITEM::TREEPROJECT_ITEM( enum TreeFileType type, const wxString& data, + wxTreeCtrl* parent ) : + wxTreeItemData() +{ + m_parent = parent; + SetType( type ); + SetFileName( data ); + SetRootFile( false ); // true only for the root item of the tree (the project name) + SetPopulated( false ); + m_state = 0; +} + + +void TREEPROJECT_ITEM::SetState( int state ) +{ + wxImageList* imglist = m_parent->GetImageList(); + + if( !imglist || state < 0 || state >= imglist->GetImageCount() / ( TREE_MAX - 2 ) ) + return; + + m_state = state; + int imgid = m_Type - 1 + state * ( TREE_MAX - 1 ); + m_parent->SetItemImage( GetId(), imgid ); + m_parent->SetItemImage( GetId(), imgid, wxTreeItemIcon_Selected ); +} + + +const wxString TREEPROJECT_ITEM::GetDir() const +{ + if( TREE_DIRECTORY == m_Type ) + return GetFileName(); + + return wxFileName( GetFileName() ).GetPath(); +} + + +bool TREEPROJECT_ITEM::Rename( const wxString& name, bool check ) +{ + // this is broken & unsafe to use on linux. + if( m_Type == TREE_DIRECTORY ) + return false; + + if( name.IsEmpty() ) + return false; + + const wxString sep = wxFileName().GetPathSeparator(); + wxString newFile; + wxString dirs = GetDir(); + + if( !dirs.IsEmpty() && GetType() != TREE_DIRECTORY ) + newFile = dirs + sep + name; + else + newFile = name; + + if( newFile == GetFileName() ) + return false; + + wxString ext = TREE_PROJECT_FRAME::GetFileExt( GetType() ); + + wxRegEx reg( wxT( "^.*\\" ) + ext + wxT( "$" ), wxRE_ICASE ); + + if( check && !ext.IsEmpty() && !reg.Matches( newFile ) ) + { + wxMessageDialog dialog( m_parent, _( + "Changing file extension will change file type.\n Do you want to continue ?" ), + _( "Rename File" ), + wxYES_NO | wxICON_QUESTION ); + + if( wxID_YES != dialog.ShowModal() ) + return false; + } + + if( !wxRenameFile( GetFileName(), newFile, false ) ) + { + wxMessageDialog( m_parent, _( "Unable to rename file ... " ), + _( "Permission error ?" ), wxICON_ERROR | wxOK ); + return false; + } + + SetFileName( newFile ); + + return true; +} + + +bool TREEPROJECT_ITEM::Delete( bool check ) +{ + wxString msg = wxString::Format( _( + "Do you really want to delete '%s'" ), + GetChars( GetFileName() ) + ); + + wxMessageDialog dialog( m_parent, msg, + _( "Delete File" ), wxYES_NO | wxICON_QUESTION ); + + if( !check || wxID_YES == dialog.ShowModal() ) + { + bool success; + + if( !wxDirExists( GetFileName() ) ) + success = wxRemoveFile( GetFileName() ); + else + { + wxArrayString filelist; + + wxDir::GetAllFiles( GetFileName(), &filelist ); + + for( unsigned int i = 0; i < filelist.Count(); i++ ) + wxRemoveFile( filelist[i] ); + + success = wxRmdir( GetFileName() ); + } + + if( success ) + m_parent->Delete( GetId() ); + + return success; + } + + return false; +} + + +void TREEPROJECT_ITEM::Activate( TREE_PROJECT_FRAME* prjframe ) +{ + wxString sep = wxFileName().GetPathSeparator(); + wxString fullFileName = GetFileName(); + wxTreeItemId id = GetId(); + + KICAD_MANAGER_FRAME* frame = prjframe->m_Parent; + wxASSERT( frame ); + + switch( GetType() ) + { + case TREE_PROJECT: + break; + + case TREE_DIRECTORY: + m_parent->Toggle( id ); + break; + + case TREE_SCHEMA: + if( fullFileName == frame->SchFileName() ) + { + // the project's schematic is opened using the *.kiface as part of this process. + // We do not call frame->RunEeschema( fullFileName ), + // because after the double click, for some reason, + // the tree project frame is brought to the foreground after Eeschema is called from here. + // Instead, we post an event, equivalent to click on the eeschema tool in command frame + wxCommandEvent evt( wxEVT_COMMAND_TOOL_CLICKED, ID_TO_SCH ); + wxPostEvent( frame, evt ); + } + else + { + // schematics not part of the project are opened in a separate process. + frame->Execute( m_parent, EESCHEMA_EXE, fullFileName ); + } + break; + + case TREE_LEGACY_PCB: + case TREE_SEXP_PCB: + if( fullFileName == frame->PcbFileName() || fullFileName == frame->PcbLegacyFileName() ) + { + // the project's BOARD is opened using the *.kiface as part of this process. + // We do not call frame->RunPcbNew( fullFileName ), + // because after the double click, for some reason, + // the tree project frame is brought to the foreground after PcbNew is called from here. + // Instead, we post an event, equivalent to simple click on the pcb editor tool in command frame + wxCommandEvent evt( wxEVT_COMMAND_TOOL_CLICKED, ID_TO_PCB ); + wxPostEvent( frame, evt ); + } + else + { + // boards not part of the project are opened in a separate process. + frame->Execute( m_parent, PCBNEW_EXE, fullFileName ); + } + break; + + case TREE_GERBER: + frame->Execute( m_parent, GERBVIEW_EXE, fullFileName ); + break; + + case TREE_HTML: + wxLaunchDefaultBrowser( fullFileName ); + break; + + case TREE_PDF: + OpenPDF( fullFileName ); + break; + +/* No, use a text editor. Netlists can only be handled sanely now from within + eeschema's launcher for the *.kiface, NOT THE EXE which is now gone. + case TREE_NET: + frame->Execute( m_parent, CVPCB_EXE, fullFileName ); + break; +*/ + + case TREE_TXT: + { + wxString editorname = Pgm().GetEditorName(); + + if( !editorname.IsEmpty() ) + frame->Execute( m_parent, editorname, fullFileName ); + } + break; + + case TREE_PAGE_LAYOUT_DESCR: + frame->Execute( m_parent, PL_EDITOR_EXE, fullFileName ); + break; + + default: + AddDelimiterString( fullFileName ); + OpenFile( fullFileName ); + break; + } +} diff --git a/kicad/class_treeproject_item.h b/kicad/class_treeproject_item.h new file mode 100644 index 0000000..052f462 --- /dev/null +++ b/kicad/class_treeproject_item.h @@ -0,0 +1,84 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras + * Copyright (C) 2004-2014 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 + */ + +#ifndef TREEPROJECT_ITEM_H_ +#define TREEPROJECT_ITEM_H_ + +/** + * Class TREEPROJECT_ITEM + * handles one item (a file or a directory name) for the tree file + */ +class TREEPROJECT_ITEM : public wxTreeItemData +{ + //friend class KICAD_MANAGER_FRAME; + +public: + + TREEPROJECT_ITEM( TreeFileType type, const wxString& data, + wxTreeCtrl* parent ); + + TREEPROJECT_ITEM() : m_parent( NULL ) { } + + TREEPROJECT_ITEM( const TREEPROJECT_ITEM& src ) : + m_Type( src.m_Type ), m_file_name( src.m_file_name ), m_parent( src.m_parent ) + { + SetState( src.m_state ); + m_IsPopulated = false; + } + + TreeFileType GetType() const { return m_Type; } + void SetType( TreeFileType aType ) { m_Type = aType; } + + const wxString& GetFileName() const { return m_file_name; } + void SetFileName( const wxString& name ) { m_file_name = name; } + + bool IsRootFile() const { return m_IsRootFile; } + void SetRootFile( bool aValue ) { m_IsRootFile = aValue; } + + bool IsPopulated() const { return m_IsPopulated; } + void SetPopulated( bool aValue ) { m_IsPopulated = aValue; } + + /** + * @return the path of an item. + * if this item is a directory, returns the stored filename + * if this is a file, returns its path + */ + const wxString GetDir() const; + + bool Rename( const wxString& name, bool check = true ); + bool Delete( bool check = true ); + void Activate( TREE_PROJECT_FRAME* prjframe ); + void SetState( int state ); + + +private: + TreeFileType m_Type; // = TREE_PROJECT, TREE_DIRECTORY ... + wxString m_file_name; // Filename for a file, or directory name + bool m_IsRootFile; // True if m_Filename is a root schematic (same name as project) + bool m_IsPopulated; // True if the name is a directory, and its content was read + wxTreeCtrl* m_parent; + int m_state; +}; + +#endif // TREEPROJECT_ITEM_H_ diff --git a/kicad/class_treeprojectfiles.cpp b/kicad/class_treeprojectfiles.cpp new file mode 100644 index 0000000..1d2b317 --- /dev/null +++ b/kicad/class_treeprojectfiles.cpp @@ -0,0 +1,112 @@ +/** + * @file class_treeprojectfiles.cpp + * this is the wxTreeCtrl that shows a KiCad tree project files + */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2012 Jean-Pierre Charras + * Copyright (C) 2004-2012 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 + */ + + +#include <fctsys.h> + +#include <kicad.h> +#include <tree_project_frame.h> +#include <class_treeprojectfiles.h> +#include <class_treeproject_item.h> + +#include <wx/regex.h> +#include <wx/imaglist.h> +#include <menus_helpers.h> + + +IMPLEMENT_ABSTRACT_CLASS( TREEPROJECTFILES, wxTreeCtrl ) + + +TREEPROJECTFILES::TREEPROJECTFILES( TREE_PROJECT_FRAME* parent ) : + wxTreeCtrl( parent, ID_PROJECT_TREE, + wxDefaultPosition, wxDefaultSize, + wxTR_HAS_BUTTONS, wxDefaultValidator, + wxT( "EDATreeCtrl" ) ) +{ + m_Parent = parent; + + // icons size is not know (depending on they are built) + // so get it: + wxSize iconsize; + wxBitmap dummy = KiBitmap( eeschema_xpm ); + iconsize.x = dummy.GetWidth(); + iconsize.y = dummy.GetHeight(); + + // Make an image list containing small icons + m_ImageList = new wxImageList( iconsize.x, iconsize.y, true, TREE_MAX ); + + m_ImageList->Add( KiBitmap( kicad_icon_small_xpm ) ); // TREE_PROJECT + m_ImageList->Add( KiBitmap( eeschema_xpm ) ); // TREE_SCHEMA + m_ImageList->Add( KiBitmap( pcbnew_xpm ) ); // TREE_LEGACY_PCB + m_ImageList->Add( KiBitmap( pcbnew_xpm ) ); // TREE_SFMT_PCB + m_ImageList->Add( KiBitmap( icon_gerbview_small_xpm ) ); // TREE_GERBER + m_ImageList->Add( KiBitmap( html_xpm ) ); // TREE_HTML + m_ImageList->Add( KiBitmap( datasheet_xpm ) ); // TREE_PDF + m_ImageList->Add( KiBitmap( icon_txt_xpm ) ); // TREE_TXT + m_ImageList->Add( KiBitmap( netlist_xpm ) ); // TREE_NET + m_ImageList->Add( KiBitmap( unknown_xpm ) ); // TREE_UNKNOWN + m_ImageList->Add( KiBitmap( directory_xpm ) ); // TREE_DIRECTORY + m_ImageList->Add( KiBitmap( icon_cvpcb_small_xpm ) ); // TREE_CMP_LINK + m_ImageList->Add( KiBitmap( tools_xpm ) ); // TREE_REPORT + m_ImageList->Add( KiBitmap( post_compo_xpm ) ); // TREE_POS + m_ImageList->Add( KiBitmap( post_drill_xpm ) ); // TREE_DRILL + m_ImageList->Add( KiBitmap( svg_file_xpm ) ); // TREE_SVG + m_ImageList->Add( KiBitmap( pagelayout_load_default_xpm ) );// TREE_PAGE_LAYOUT_DESCR + m_ImageList->Add( KiBitmap( module_xpm ) ); // TREE_FOOTPRINT_FILE + m_ImageList->Add( KiBitmap( library_xpm ) ); // TREE_SCHEMATIC_LIBFILE + + SetImageList( m_ImageList ); +} + + +TREEPROJECTFILES::~TREEPROJECTFILES() +{ + delete m_ImageList; +} + + +int TREEPROJECTFILES::OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 ) +{ + TREEPROJECT_ITEM* myitem1 = (TREEPROJECT_ITEM*) GetItemData( item1 ); + TREEPROJECT_ITEM* myitem2 = (TREEPROJECT_ITEM*) GetItemData( item2 ); + + if( myitem1->GetType() == TREE_DIRECTORY && myitem2->GetType() != TREE_DIRECTORY ) + return -1; + + if( myitem2->GetType() == TREE_DIRECTORY && myitem1->GetType() != TREE_DIRECTORY ) + return 1; + + if( myitem1->IsRootFile() && !myitem2->IsRootFile() ) + return -1; + + if( myitem2->IsRootFile() && !myitem1->IsRootFile() ) + return 1; + + return myitem1->GetFileName().CmpNoCase( myitem2->GetFileName() ); +} + diff --git a/kicad/class_treeprojectfiles.h b/kicad/class_treeprojectfiles.h new file mode 100644 index 0000000..d10c53e --- /dev/null +++ b/kicad/class_treeprojectfiles.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras + * Copyright (C) 2004-2014 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 class_treeprojectfiles.h + */ + +#ifndef CLASS_TREEPROJECTFILES_H +#define CLASS_TREEPROJECTFILES_H + +/** Class TREEPROJECTFILES + * This is the class to show (as a tree) the files in the project directory + */ +class TREEPROJECTFILES : public wxTreeCtrl +{ + DECLARE_DYNAMIC_CLASS( TREEPROJECTFILES ) +private: + TREE_PROJECT_FRAME* m_Parent; + wxImageList* m_ImageList; + +public: + + TREE_PROJECT_FRAME* GetParent() const + { + return m_Parent; + } + + + TREEPROJECTFILES( TREE_PROJECT_FRAME* parent ); + ~TREEPROJECTFILES(); +private: + /* overridden sort function */ + int OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 ); +}; + +#endif // CLASS_TREEPROJECTFILES_H diff --git a/kicad/commandframe.cpp b/kicad/commandframe.cpp new file mode 100644 index 0000000..dca9580 --- /dev/null +++ b/kicad/commandframe.cpp @@ -0,0 +1,116 @@ +/** + * @file commandframe.cpp + * @brief Frame showing fast launch buttons and messages box + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2012 Jean-Pierre Charras + * Copyright (C) 2004-2012 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 + */ + + +#include <fctsys.h> +#include <macros.h> + +#include <kicad.h> +#include <menus_helpers.h> + + +LAUNCHER_PANEL::LAUNCHER_PANEL( wxWindow* parent ) : + wxPanel( parent, wxID_ANY ) +{ + m_bitmapButtons_maxHeigth = 0; + m_buttonSeparation = 10; // control of command buttons position + m_buttonsListPosition.x = m_buttonSeparation; + m_buttonsListPosition.y = m_buttonSeparation; + m_buttonLastPosition = m_buttonsListPosition; + + // Add bitmap buttons to launch KiCad utilities: + CreateCommandToolbar(); +} + +int LAUNCHER_PANEL::GetPanelHeight() const +{ + int height = m_buttonsListPosition.y + m_bitmapButtons_maxHeigth + + m_buttonSeparation; + return height; +} + +/** + * Function CreateCommandToolbar + * create the buttons to call Eeschema CvPcb, Pcbnew and GerbView + */ +void LAUNCHER_PANEL::CreateCommandToolbar() +{ + wxBitmapButton* btn; + + btn = AddBitmapButton( ID_TO_SCH, KiBitmap( icon_eeschema_xpm ) ); + btn->SetToolTip( _( "Eeschema - Electronic schematic editor" ) ); + + btn = AddBitmapButton( ID_TO_SCH_LIB_EDITOR, KiBitmap( libedit_icon_xpm ) ); + btn->SetToolTip( _( "Schematic library editor" ) ); + + btn = AddBitmapButton( ID_TO_PCB, KiBitmap( icon_pcbnew_xpm ) ); + btn->SetToolTip( _( "Pcbnew - Printed circuit board editor" ) ); + + btn = AddBitmapButton( ID_TO_PCB_FP_EDITOR, KiBitmap( icon_modedit_xpm ) ); + btn->SetToolTip( _( "PCB footprint editor" ) ); + + btn = AddBitmapButton( ID_TO_GERBVIEW, KiBitmap( icon_gerbview_xpm ) ); + btn->SetToolTip( _( "GerbView - Gerber viewer" ) ); + + btn = AddBitmapButton( ID_TO_BITMAP_CONVERTER, KiBitmap( icon_bitmap2component_xpm ) ); + btn->SetToolTip( _( + "Bitmap2Component - Convert bitmap images to Eeschema\n" + "or Pcbnew elements" ) ); + + btn = AddBitmapButton( ID_TO_PCB_CALCULATOR, KiBitmap( icon_pcbcalculator_xpm ) ); + btn->SetToolTip( _( "Pcb calculator - Calculator for components, track width, etc." ) ); + + btn = AddBitmapButton( ID_TO_PL_EDITOR, KiBitmap( icon_pagelayout_editor_xpm ) ); + btn->SetToolTip( _( "Pl editor - Worksheet layout editor" ) ); +} + + +/** + * Function AddBitmapButton + * add a Bitmap Button (fast launch button) to the buttons panel + * @param aId = the button id + * @param aBitmap = the wxBitmap used to create the button + */ +wxBitmapButton* LAUNCHER_PANEL::AddBitmapButton( wxWindowID aId, const wxBitmap& aBitmap ) +{ + wxPoint buttPos = m_buttonLastPosition; + wxSize buttSize; + int btn_margin = 10; // extra margin around the bitmap. + + buttSize.x = aBitmap.GetWidth() + btn_margin; + buttSize.y = aBitmap.GetHeight() + btn_margin; + + if( m_bitmapButtons_maxHeigth < buttSize.y ) + m_bitmapButtons_maxHeigth = buttSize.y; + + wxBitmapButton* btn = new wxBitmapButton( this, aId, aBitmap, buttPos, buttSize ); + m_buttonLastPosition.x += buttSize.x + m_buttonSeparation; + + return btn; +} diff --git a/kicad/dialogs/dialog_template_selector.cpp b/kicad/dialogs/dialog_template_selector.cpp new file mode 100644 index 0000000..f36f66d --- /dev/null +++ b/kicad/dialogs/dialog_template_selector.cpp @@ -0,0 +1,280 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Brian Sidebotham <brian.sidebotham@gmail.com> + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 + */ + +#include "dialog_template_selector.h" + +#include <wx/dir.h> +#include <wx/settings.h> + + +TEMPLATE_SELECTION_PANEL::TEMPLATE_SELECTION_PANEL( wxNotebookPage* aParent, + const wxString& aPath ) : + TEMPLATE_SELECTION_PANEL_BASE( aParent ) +{ + m_parent = aParent; + m_templatesPath = aPath; +} + + +TEMPLATE_WIDGET::TEMPLATE_WIDGET( wxWindow* aParent, DIALOG_TEMPLATE_SELECTOR* aDialog ) : + TEMPLATE_WIDGET_BASE( aParent ) +{ + m_parent = aParent; + m_dialog = aDialog; + + // wxWidgets_3.xx way of doing the same... + // Bind(wxEVT_LEFT_DOWN, &TEMPLATE_WIDGET::OnMouse, this ); + + m_bitmapIcon->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::OnMouse ), NULL, this ); + m_staticTitle->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::OnMouse ), NULL, this ); + + // We're not selected until we're clicked + Unselect(); + + // Start with template being NULL + m_currTemplate = NULL; +} + + +void TEMPLATE_WIDGET::Select() +{ + m_dialog->SetWidget( this ); + SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNHIGHLIGHT ) ); + m_selected = true; + Refresh(); +} + + +void TEMPLATE_WIDGET::Unselect() +{ + SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_selected = false; + Refresh(); +} + + +void TEMPLATE_WIDGET::SetTemplate(PROJECT_TEMPLATE* aTemplate) +{ + m_currTemplate = aTemplate; + m_staticTitle->SetLabel( *(aTemplate->GetTitle()) ); + m_bitmapIcon->SetBitmap( *(aTemplate->GetIcon()) ); +} + + +void TEMPLATE_WIDGET::OnMouse( wxMouseEvent& event ) +{ + // Toggle selection here + Select(); + event.Skip(); +} + + +void DIALOG_TEMPLATE_SELECTOR::onNotebookResize(wxSizeEvent& event) +{ + for( size_t i=0; i < m_notebook->GetPageCount(); i++ ) + { + m_panels[i]->SetSize( m_notebook->GetSize().GetWidth() - 6, 140 ); + m_panels[i]->m_SizerBase->FitInside( m_panels[i] ); + m_panels[i]->m_scrolledWindow->SetSize( m_panels[i]->GetSize().GetWidth() - 6, + m_panels[i]->GetSize().GetHeight() - 6 ); + m_panels[i]->m_SizerChoice->FitInside( m_panels[i]->m_scrolledWindow ); + } + m_notebook->Refresh(); + + event.Skip(); +} + +void DIALOG_TEMPLATE_SELECTOR::OnPageChange( wxNotebookEvent& event ) +{ + int page = m_notebook->GetSelection(); + + if( page != wxNOT_FOUND && (unsigned)page < m_panels.size() ) + m_tcTemplatePath->SetValue( m_panels[page]->GetPath() ); +} + + +DIALOG_TEMPLATE_SELECTOR::DIALOG_TEMPLATE_SELECTOR( wxWindow* aParent ) : + DIALOG_TEMPLATE_SELECTOR_BASE( aParent ) +{ + m_htmlWin->SetPage( _( "<html><h1>Template Selector</h1></html>" ) ); + m_notebook->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_TEMPLATE_SELECTOR::onNotebookResize ), NULL, this ); + m_selectedWidget = NULL; +} + + +void DIALOG_TEMPLATE_SELECTOR::SetWidget( TEMPLATE_WIDGET* aWidget ) +{ + if( m_selectedWidget != NULL ) + m_selectedWidget->Unselect(); + + m_selectedWidget = aWidget; + SetHtml( m_selectedWidget->GetTemplate()->GetHtmlFile() ); +} + +void DIALOG_TEMPLATE_SELECTOR::AddTemplate( int aPage, PROJECT_TEMPLATE* aTemplate ) +{ + TEMPLATE_WIDGET* w = new TEMPLATE_WIDGET( m_panels[aPage]->m_scrolledWindow, this ); + w->SetTemplate( aTemplate ); + + m_panels[aPage]->m_SizerChoice->Add( w ); + m_panels[aPage]->m_SizerChoice->Layout(); + m_panels[aPage]->SetSize( m_notebook->GetSize().GetWidth() - 6, 140 ); + m_panels[aPage]->m_SizerBase->FitInside( m_panels[aPage] ); + m_panels[aPage]->m_scrolledWindow->SetSize( m_panels[aPage]->GetSize().GetWidth() - 6, + m_panels[aPage]->GetSize().GetHeight() - 6 ); + m_panels[aPage]->m_SizerChoice->FitInside( m_panels[aPage]->m_scrolledWindow ); + + m_notebook->Refresh(); +} + + +PROJECT_TEMPLATE* DIALOG_TEMPLATE_SELECTOR::GetSelectedTemplate() +{ + return m_selectedWidget? m_selectedWidget->GetTemplate() : NULL; +} + +void DIALOG_TEMPLATE_SELECTOR::AddTemplatesPage( const wxString& aTitle, wxFileName& aPath ) +{ + wxNotebookPage* newPage = new wxNotebookPage( m_notebook, wxID_ANY ); + + aPath.Normalize(); + wxString path = aPath.GetFullPath(); // caller ensures this ends with file separator. + + TEMPLATE_SELECTION_PANEL* tpanel = new TEMPLATE_SELECTION_PANEL( newPage, path ); + m_panels.push_back( tpanel ); + + m_notebook->AddPage( newPage, aTitle ); + + if( m_notebook->GetPageCount() == 1 ) + m_tcTemplatePath->SetValue( path ); + + buildPageContent( path, m_notebook->GetPageCount() - 1 ); +} + +void DIALOG_TEMPLATE_SELECTOR::buildPageContent( const wxString& aPath, int aPage ) +{ + // Get a list of files under the template path to include as choices... + wxArrayString files; + wxDir dir; + + if( dir.Open( aPath ) ) + { + wxDir sub_dir; + wxString sub_name; + + bool cont = dir.GetFirst( &sub_name, wxEmptyString, wxDIR_DIRS ); + while( cont ) + { + wxString sub_full = aPath + sub_name; + if( sub_dir.Open( sub_full ) ) + { + files.Add( sub_name ); + + PROJECT_TEMPLATE* pt = new PROJECT_TEMPLATE( sub_full ); + AddTemplate( aPage, pt ); + } + + cont = dir.GetNext( &sub_name ); + } + } +} + + +void DIALOG_TEMPLATE_SELECTOR::onDirectoryBrowseClicked( wxCommandEvent& event ) +{ + wxFileName fn; + fn.AssignDir( m_tcTemplatePath->GetValue() ); + fn.Normalize(); + wxString currPath = fn.GetFullPath(); + + wxDirDialog dirDialog( this, _( "Select Templates Directory" ), + currPath, + wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST ); + + if( dirDialog.ShowModal() != wxID_OK ) + return; + + wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() ); + + m_tcTemplatePath->SetValue( dirName.GetFullPath() ); + + if( currPath == m_tcTemplatePath->GetValue() ) + return; // No change + + // Rebuild the page from the new templates path: + replaceCurrentPage(); +} + + +void DIALOG_TEMPLATE_SELECTOR::onValidatePath( wxCommandEvent& event ) +{ + int page = m_notebook->GetSelection(); + + if( page < 0 ) + return; // Should not happen + + wxString currPath = m_tcTemplatePath->GetValue(); + + if( currPath == m_panels[page]->GetPath() ) // No change + return; + + wxFileName fn; + fn.AssignDir( m_tcTemplatePath->GetValue() ); + fn.Normalize(); + currPath = fn.GetFullPath(); + m_tcTemplatePath->SetValue( currPath ); + + replaceCurrentPage(); +} + + +void DIALOG_TEMPLATE_SELECTOR::replaceCurrentPage() +{ + // Rebuild the page from the new templates path: + int page = m_notebook->GetSelection(); + + if( page < 0 ) + return; // Should not happen + + wxString title = m_notebook->GetPageText( page ); + wxString currPath = m_tcTemplatePath->GetValue(); + + m_notebook->DeletePage( page ); + + wxNotebookPage* newPage = new wxNotebookPage( m_notebook, wxID_ANY ); + TEMPLATE_SELECTION_PANEL* tpanel = new TEMPLATE_SELECTION_PANEL( newPage, currPath ); + m_panels[page] = tpanel; + m_notebook->InsertPage( page, newPage, title, true ); + + buildPageContent( m_tcTemplatePath->GetValue(), page ); + + m_selectedWidget = NULL; +} + + +void DIALOG_TEMPLATE_SELECTOR::OnHtmlLinkActivated( wxHtmlLinkEvent& event ) +{ + wxString url = event.GetLinkInfo().GetHref(); + wxLaunchDefaultBrowser( url); +} diff --git a/kicad/dialogs/dialog_template_selector.fbp b/kicad/dialogs/dialog_template_selector.fbp new file mode 100644 index 0000000..687a923 --- /dev/null +++ b/kicad/dialogs/dialog_template_selector.fbp @@ -0,0 +1,1105 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="13" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">connect</property> + <property name="file">dialog_template_selector_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="internationalize">1</property> + <property name="name">DIALOG_TEMPLATE_SELECTOR_BASE</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_lua_events">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="ui_table">UI</property> + <property name="use_enum">0</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center">wxBOTH</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size">640,480</property> + <property name="name">DIALOG_TEMPLATE_SELECTOR_BASE</property> + <property name="pos"></property> + <property name="size">640,480</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">Project Template Selector</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnActivate"></event> + <event name="OnActivateApp"></event> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnClose"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHibernate"></event> + <event name="OnIconize"></event> + <event name="OnIdle"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bmainSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">3</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">0</property> + <object class="wxNotebook" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="bitmapsize"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size">-1,-1</property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">-1,-1</property> + <property name="moveable">1</property> + <property name="name">m_notebook</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnNotebookPageChanged">OnPageChange</event> + <event name="OnNotebookPageChanging"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">3</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxHtmlWindow" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_htmlWin</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size">-1,-1</property> + <property name="style">wxHW_SCROLLBAR_AUTO</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHtmlCellClicked"></event> + <event name="OnHtmlCellHover"></event> + <event name="OnHtmlLinkClicked">OnHtmlLinkActivated</event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxTOP|wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Template path</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticTextTpath</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bsizerTemplateSelector</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property> + <property name="proportion">1</property> + <object class="wxTextCtrl" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="maxlength"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_tcTemplatePath</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxTE_PROCESS_ENTER</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnText"></event> + <event name="OnTextEnter"></event> + <event name="OnTextMaxLen"></event> + <event name="OnTextURL"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Browse</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonBrowse</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxBU_EXACTFIT</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">onDirectoryBrowseClicked</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Validate</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonValidate</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxBU_EXACTFIT</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">onValidatePath</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">0</property> + <object class="wxStaticLine" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticline</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxLI_HORIZONTAL</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">3</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxStdDialogButtonSizer" expanded="1"> + <property name="Apply">0</property> + <property name="Cancel">1</property> + <property name="ContextHelp">0</property> + <property name="Help">0</property> + <property name="No">0</property> + <property name="OK">1</property> + <property name="Save">0</property> + <property name="Yes">0</property> + <property name="minimum_size"></property> + <property name="name">m_sdbSizer</property> + <property name="permission">protected</property> + <event name="OnApplyButtonClick"></event> + <event name="OnCancelButtonClick"></event> + <event name="OnContextHelpButtonClick"></event> + <event name="OnHelpButtonClick"></event> + <event name="OnNoButtonClick"></event> + <event name="OnOKButtonClick"></event> + <event name="OnSaveButtonClick"></event> + <event name="OnYesButtonClick"></event> + </object> + </object> + </object> + </object> + <object class="Panel" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size">-1,-1</property> + <property name="minimum_size">-1,-1</property> + <property name="name">TEMPLATE_SELECTION_PANEL_BASE</property> + <property name="pos"></property> + <property name="size">-1,140</property> + <property name="subclass"></property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxNO_BORDER|wxTAB_TRAVERSAL</property> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">m_SizerBase</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">public</property> + <object class="sizeritem" expanded="1"> + <property name="border">3</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">0</property> + <object class="wxScrolledWindow" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_scrolledWindow</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">public</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="scroll_rate_x">5</property> + <property name="scroll_rate_y">5</property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxHSCROLL</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">m_SizerChoice</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">public</property> + </object> + </object> + </object> + </object> + </object> + <object class="Panel" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size">74,-1</property> + <property name="minimum_size">74,-1</property> + <property name="name">TEMPLATE_WIDGET_BASE</property> + <property name="pos"></property> + <property name="size">74,-1</property> + <property name="subclass"></property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxTAB_TRAVERSAL</property> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizer4</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">3</property> + <property name="flag">wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxStaticBitmap" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="bitmap"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_bitmapIcon</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size">64,64</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">3</property> + <property name="flag">wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxStaticText" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Project Template Title</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticTitle</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxALIGN_CENTRE</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">150</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/kicad/dialogs/dialog_template_selector.h b/kicad/dialogs/dialog_template_selector.h new file mode 100644 index 0000000..17a7a62 --- /dev/null +++ b/kicad/dialogs/dialog_template_selector.h @@ -0,0 +1,128 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Brian Sidebotham <brian.sidebotham@gmail.com> + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 + */ + +#ifndef PROJECT_TEMPLATE_SELECTOR_H +#define PROJECT_TEMPLATE_SELECTOR_H + +#include <dialogs/dialog_template_selector_base.h> +#include "project_template.h" + +class DIALOG_TEMPLATE_SELECTOR; + +class TEMPLATE_WIDGET : public TEMPLATE_WIDGET_BASE +{ +protected: + DIALOG_TEMPLATE_SELECTOR* m_dialog; + wxWindow* m_parent; + wxPanel* m_panel; + bool m_selected; + + PROJECT_TEMPLATE* m_currTemplate; + + void OnKillFocus( wxFocusEvent& event ); + void OnMouse( wxMouseEvent& event ); + +public: + TEMPLATE_WIDGET( wxWindow* aParent, DIALOG_TEMPLATE_SELECTOR* aDialog ); + + /** + * Set the project template for this widget, which will determine the icon and title + * associated with this project template widget + */ + void SetTemplate(PROJECT_TEMPLATE* aTemplate); + + PROJECT_TEMPLATE* GetTemplate() { return m_currTemplate; } + + void Select(); + void Unselect(); + +private: + bool IsSelected() { return m_selected; } +}; + + +class TEMPLATE_SELECTION_PANEL : public TEMPLATE_SELECTION_PANEL_BASE +{ +protected: + wxNotebookPage* m_parent; + wxString m_templatesPath; ///< the path to access to the folder + ///< containing the templates (which are also folders) + +public: + /** + * @param aParent The window creating the dialog + * @param aPath the path + */ + TEMPLATE_SELECTION_PANEL( wxNotebookPage* aParent, const wxString& aPath ); + + const wxString& GetPath() { return m_templatesPath; } +}; + + +class DIALOG_TEMPLATE_SELECTOR : public DIALOG_TEMPLATE_SELECTOR_BASE +{ +protected: + std::vector<TEMPLATE_SELECTION_PANEL*> m_panels; + TEMPLATE_WIDGET* m_selectedWidget; + + void AddTemplate( int aPage, PROJECT_TEMPLATE* aTemplate ); + +public: + DIALOG_TEMPLATE_SELECTOR( wxWindow* aParent ); + + /** + * Add a new page with \a aTitle, populated with templates from \a aPath + * - All directories under the path are treated as templates + * @param aTitle = the title of the wxNoteBook page + * @param aPath = the path of the main folder containing templates + */ + void AddTemplatesPage( const wxString& aTitle, wxFileName& aPath ); + + /** + * @return the selected template, or NULL + */ + PROJECT_TEMPLATE* GetSelectedTemplate(); + +private: + + void SetHtml( wxFileName aFilename ) + { + m_htmlWin->LoadPage( aFilename.GetFullPath() ); + } + +public: + void SetWidget( TEMPLATE_WIDGET* aWidget ); + +private: + void buildPageContent( const wxString& aPath, int aPage ); + void replaceCurrentPage(); + + void onNotebookResize( wxSizeEvent& event ); + void OnPageChange( wxNotebookEvent& event ); + void onDirectoryBrowseClicked( wxCommandEvent& event ); + void onValidatePath( wxCommandEvent& event ); + void OnHtmlLinkActivated( wxHtmlLinkEvent& event ); +}; + +#endif diff --git a/kicad/dialogs/dialog_template_selector_base.cpp b/kicad/dialogs/dialog_template_selector_base.cpp new file mode 100644 index 0000000..7328f89 --- /dev/null +++ b/kicad/dialogs/dialog_template_selector_base.cpp @@ -0,0 +1,125 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_template_selector_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_TEMPLATE_SELECTOR_BASE::DIALOG_TEMPLATE_SELECTOR_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( 640,480 ), wxDefaultSize ); + + wxBoxSizer* bmainSizer; + bmainSizer = new wxBoxSizer( wxVERTICAL ); + + m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + bmainSizer->Add( m_notebook, 0, wxEXPAND | wxALL, 3 ); + + m_htmlWin = new wxHtmlWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxHW_SCROLLBAR_AUTO ); + bmainSizer->Add( m_htmlWin, 1, wxALL|wxEXPAND, 3 ); + + m_staticTextTpath = new wxStaticText( this, wxID_ANY, _("Template path"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTpath->Wrap( -1 ); + bmainSizer->Add( m_staticTextTpath, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bsizerTemplateSelector; + bsizerTemplateSelector = new wxBoxSizer( wxHORIZONTAL ); + + m_tcTemplatePath = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + bsizerTemplateSelector->Add( m_tcTemplatePath, 1, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonBrowse = new wxButton( this, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT ); + bsizerTemplateSelector->Add( m_buttonBrowse, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + + m_buttonValidate = new wxButton( this, wxID_ANY, _("Validate"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT ); + bsizerTemplateSelector->Add( m_buttonValidate, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + + + bmainSizer->Add( bsizerTemplateSelector, 0, wxEXPAND, 5 ); + + m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bmainSizer->Add( m_staticline, 0, wxEXPAND | wxALL, 5 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + bmainSizer->Add( m_sdbSizer, 0, wxALL|wxEXPAND, 3 ); + + + this->SetSizer( bmainSizer ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + m_notebook->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::OnPageChange ), NULL, this ); + m_htmlWin->Connect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::OnHtmlLinkActivated ), NULL, this ); + m_buttonBrowse->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::onDirectoryBrowseClicked ), NULL, this ); + m_buttonValidate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::onValidatePath ), NULL, this ); +} + +DIALOG_TEMPLATE_SELECTOR_BASE::~DIALOG_TEMPLATE_SELECTOR_BASE() +{ + // Disconnect Events + m_notebook->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::OnPageChange ), NULL, this ); + m_htmlWin->Disconnect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::OnHtmlLinkActivated ), NULL, this ); + m_buttonBrowse->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::onDirectoryBrowseClicked ), NULL, this ); + m_buttonValidate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TEMPLATE_SELECTOR_BASE::onValidatePath ), NULL, this ); + +} + +TEMPLATE_SELECTION_PANEL_BASE::TEMPLATE_SELECTION_PANEL_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) +{ + m_SizerBase = new wxBoxSizer( wxHORIZONTAL ); + + m_scrolledWindow = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL ); + m_scrolledWindow->SetScrollRate( 5, 5 ); + m_SizerChoice = new wxBoxSizer( wxHORIZONTAL ); + + + m_scrolledWindow->SetSizer( m_SizerChoice ); + m_scrolledWindow->Layout(); + m_SizerChoice->Fit( m_scrolledWindow ); + m_SizerBase->Add( m_scrolledWindow, 0, wxEXPAND | wxALL, 3 ); + + + this->SetSizer( m_SizerBase ); + this->Layout(); +} + +TEMPLATE_SELECTION_PANEL_BASE::~TEMPLATE_SELECTION_PANEL_BASE() +{ +} + +TEMPLATE_WIDGET_BASE::TEMPLATE_WIDGET_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) +{ + this->SetMinSize( wxSize( 74,-1 ) ); + this->SetMaxSize( wxSize( 74,-1 ) ); + + wxBoxSizer* bSizer4; + bSizer4 = new wxBoxSizer( wxVERTICAL ); + + m_bitmapIcon = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 64,64 ), 0 ); + bSizer4->Add( m_bitmapIcon, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3 ); + + m_staticTitle = new wxStaticText( this, wxID_ANY, _("Project Template Title"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE ); + m_staticTitle->Wrap( 150 ); + bSizer4->Add( m_staticTitle, 1, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3 ); + + + this->SetSizer( bSizer4 ); + this->Layout(); +} + +TEMPLATE_WIDGET_BASE::~TEMPLATE_WIDGET_BASE() +{ +} diff --git a/kicad/dialogs/dialog_template_selector_base.h b/kicad/dialogs/dialog_template_selector_base.h new file mode 100644 index 0000000..6bfcbea --- /dev/null +++ b/kicad/dialogs/dialog_template_selector_base.h @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_TEMPLATE_SELECTOR_BASE_H__ +#define __DIALOG_TEMPLATE_SELECTOR_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include <wx/gdicmn.h> +#include <wx/notebook.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/string.h> +#include <wx/html/htmlwin.h> +#include <wx/stattext.h> +#include <wx/textctrl.h> +#include <wx/button.h> +#include <wx/sizer.h> +#include <wx/statline.h> +#include <wx/dialog.h> +#include <wx/scrolwin.h> +#include <wx/panel.h> +#include <wx/bitmap.h> +#include <wx/image.h> +#include <wx/icon.h> +#include <wx/statbmp.h> + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_TEMPLATE_SELECTOR_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_TEMPLATE_SELECTOR_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxNotebook* m_notebook; + wxHtmlWindow* m_htmlWin; + wxStaticText* m_staticTextTpath; + wxTextCtrl* m_tcTemplatePath; + wxButton* m_buttonBrowse; + wxButton* m_buttonValidate; + wxStaticLine* m_staticline; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnPageChange( wxNotebookEvent& event ) { event.Skip(); } + virtual void OnHtmlLinkActivated( wxHtmlLinkEvent& event ) { event.Skip(); } + virtual void onDirectoryBrowseClicked( wxCommandEvent& event ) { event.Skip(); } + virtual void onValidatePath( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_TEMPLATE_SELECTOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Project Template Selector"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 640,480 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_TEMPLATE_SELECTOR_BASE(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class TEMPLATE_SELECTION_PANEL_BASE +/////////////////////////////////////////////////////////////////////////////// +class TEMPLATE_SELECTION_PANEL_BASE : public wxPanel +{ + private: + + protected: + + public: + wxBoxSizer* m_SizerBase; + wxScrolledWindow* m_scrolledWindow; + wxBoxSizer* m_SizerChoice; + + TEMPLATE_SELECTION_PANEL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,140 ), long style = wxNO_BORDER|wxTAB_TRAVERSAL ); + ~TEMPLATE_SELECTION_PANEL_BASE(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class TEMPLATE_WIDGET_BASE +/////////////////////////////////////////////////////////////////////////////// +class TEMPLATE_WIDGET_BASE : public wxPanel +{ + private: + + protected: + wxStaticBitmap* m_bitmapIcon; + wxStaticText* m_staticTitle; + + public: + + TEMPLATE_WIDGET_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 74,-1 ), long style = wxTAB_TRAVERSAL ); + ~TEMPLATE_WIDGET_BASE(); + +}; + +#endif //__DIALOG_TEMPLATE_SELECTOR_BASE_H__ diff --git a/kicad/file_pro.icns b/kicad/file_pro.icns Binary files differnew file mode 100644 index 0000000..28921b1 --- /dev/null +++ b/kicad/file_pro.icns diff --git a/kicad/files-io.cpp b/kicad/files-io.cpp new file mode 100644 index 0000000..805c722 --- /dev/null +++ b/kicad/files-io.cpp @@ -0,0 +1,249 @@ +/** + * @file kicad/files-io.cpp + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2017 Jean-Pierre Charras + * Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.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 + */ + +#include <fctsys.h> +#include <pgm_kicad.h> +#include <kiway.h> +#include <wx/fs_zip.h> +#include <wx/zipstrm.h> +#include <wx/docview.h> +#include <wx/wfstream.h> +#include <wx/zstream.h> +#include <wx/dir.h> + +#include <confirm.h> +#include <gestfich.h> +#include <macros.h> + +#include <kicad.h> + +#define ZipFileExtension wxT( "zip" ) +#define ZipFileWildcard _( "Zip file (*.zip)|*.zip" ) + + +void KICAD_MANAGER_FRAME::OnFileHistory( wxCommandEvent& event ) +{ + wxString fn = GetFileFromHistory( event.GetId(), + _( "KiCad project file" ), &Pgm().GetFileHistory() ); + + if( fn.size() ) + { + // Any open KIFACE's must be closed before changing the project. + // We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project, + // and then break one project. + // Remember when saving files, the full path is build from the current project path + // User is prompted here to close those KIWAY_PLAYERs: + if( !Kiway.PlayersClose( false ) ) + return; + + // We can now set the new project filename and load this project + SetProjectFileName( fn ); + wxCommandEvent cmd( 0, wxID_ANY ); + OnLoadProject( cmd ); + } +} + + +void KICAD_MANAGER_FRAME::OnUnarchiveFiles( wxCommandEvent& event ) +{ + wxFileName fn = GetProjectFileName(); + + fn.SetExt( ZipFileExtension ); + + wxFileDialog zipfiledlg( this, _( "Unzip Project" ), fn.GetPath(), + fn.GetFullName(), ZipFileWildcard, + wxFD_OPEN | wxFD_FILE_MUST_EXIST ); + + if( zipfiledlg.ShowModal() == wxID_CANCEL ) + return; + + wxString msg = wxString::Format( _("\nOpen '%s'\n" ), GetChars( zipfiledlg.GetPath() ) ); + PrintMsg( msg ); + + wxDirDialog dirDlg( this, _( "Target Directory" ), fn.GetPath(), + wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST ); + + if( dirDlg.ShowModal() == wxID_CANCEL ) + return; + + wxString unzipDir = dirDlg.GetPath() + wxT( "/" ); + msg.Printf( _( "Unzipping project in '%s'\n" ), GetChars( unzipDir ) ); + PrintMsg( msg ); + + wxFileSystem zipfilesys; + + zipfilesys.AddHandler( new wxZipFSHandler ); + zipfilesys.ChangePathTo( zipfiledlg.GetPath() + wxT( "#zip:" ), true ); + + wxFSFile* zipfile = NULL; + wxString localfilename = zipfilesys.FindFirst( wxT( "*.*" ) ); + + while( !localfilename.IsEmpty() ) + { + zipfile = zipfilesys.OpenFile( localfilename ); + if( !zipfile ) + { + DisplayError( this, wxT( "Zip file read error" ) ); + break; + } + + wxFileName uzfn = localfilename.AfterLast( ':' ); + uzfn.MakeAbsolute( unzipDir ); + wxString unzipfilename = uzfn.GetFullPath(); + + msg.Printf( _( "Extract file '%s'" ), GetChars( unzipfilename ) ); + PrintMsg( msg ); + + wxInputStream* stream = zipfile->GetStream(); + wxFFileOutputStream* ofile = new wxFFileOutputStream( unzipfilename ); + + if( ofile->Ok() ) + { + ofile->Write( *stream ); + PrintMsg( _( " OK\n" ) ); + } + else + PrintMsg( _( " *ERROR*\n" ) ); + + delete ofile; + delete zipfile; + + localfilename = zipfilesys.FindNext(); + } + + PrintMsg( wxT( "** end **\n" ) ); +} + + +void KICAD_MANAGER_FRAME::OnArchiveFiles( wxCommandEvent& event ) +{ + // List of file extensions to save. + static const wxChar* extentionList[] = { + wxT( "*.sch" ), wxT( "*.lib" ), wxT( "*.mod" ), wxT( "*.cmp" ), + wxT( "*.brd" ), wxT( "*.kicad_pcb" ), wxT( "*.gbr" ), wxT( "*.pos" ), + wxT( "*.net" ), wxT( "*.pro" ), wxT( "*.drl" ), wxT( "*.py" ), + wxT( "*.pdf" ), wxT( "*.txt" ), wxT( "*.dcm" ), wxT( "*.kicad_wks" ), + }; + + wxString msg; + wxFileName fileName = GetProjectFileName(); + wxString oldCwd = wxGetCwd(); + + fileName.SetExt( wxT( "zip" ) ); + + wxFileDialog dlg( this, _( "Archive Project Files" ), + fileName.GetPath(), fileName.GetFullName(), + ZipFileWildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + wxFileName zip = dlg.GetPath(); + + wxString currdirname = fileName.GetPathWithSep(); + wxDir dir( currdirname ); + + if( !dir.IsOpened() ) // wxWidgets display a error message on issue. + return; + + wxSetWorkingDirectory( currdirname ); + + // Prepare the zip file + wxString zipfilename = zip.GetFullPath(); + + wxFFileOutputStream ostream( zipfilename ); + + if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir + { + wxMessageBox( wxString::Format( _( "Unable to create zip archive file '%s'" ), zipfilename ) ); + return; + } + + wxZipOutputStream zipstream( ostream ); + + // Build list of filenames to put in zip archive + wxString currFilename; + + wxArrayString files; + + for( unsigned ii = 0; ii < DIM( extentionList ); ii++ ) + wxDir::GetAllFiles( currdirname, &files, extentionList[ii] ); + + files.Sort(); + + int zipBytesCnt = 0; + + for( unsigned ii = 0; ii < files.GetCount(); ii++ ) + { + wxFileSystem fsfile; + + wxFileName curr_fn( files[ii] ); + curr_fn.MakeRelativeTo( currdirname ); + currFilename = curr_fn.GetFullPath(); + + msg.Printf( _( "Archive file <%s>" ), GetChars( currFilename ) ); + PrintMsg( msg ); + + // Read input file and add it to the zip file: + wxFSFile* infile = fsfile.OpenFile( currFilename ); + + if( infile ) + { + zipstream.PutNextEntry( currFilename, infile->GetModificationTime() ); + infile->GetStream()->Read( zipstream ); + zipstream.CloseEntry(); + int zippedsize = zipstream.GetSize() - zipBytesCnt; + zipBytesCnt = zipstream.GetSize(); + PrintMsg( wxT(" ") ); + msg.Printf( _( "(%lu bytes, compressed %d bytes)\n" ), + (unsigned long)infile->GetStream()->GetSize(), zippedsize ); + PrintMsg( msg ); + delete infile; + } + else + PrintMsg( _( " >>Error\n" ) ); + } + + zipBytesCnt = ostream.GetSize(); + + if( zipstream.Close() ) + { + msg.Printf( _( "\nZip archive <%s> created (%d bytes)" ), + GetChars( zipfilename ), zipBytesCnt ); + PrintMsg( msg ); + PrintMsg( wxT( "\n** end **\n" ) ); + } + else + { + msg.Printf( wxT( "Unable to create archive <%s>, abort\n" ), + GetChars( zipfilename ) ); + PrintMsg( msg ); + } + + wxSetWorkingDirectory( oldCwd ); +} diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp new file mode 100644 index 0000000..4a2d25a --- /dev/null +++ b/kicad/kicad.cpp @@ -0,0 +1,310 @@ +/** + * @file kicad.cpp + * @brief Main KiCad Project manager file + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr + * 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 + */ + + +#include <macros.h> +#include <fctsys.h> +#include <wx/stdpaths.h> +#include <kicad.h> +#include <kiway.h> +#include <pgm_kicad.h> +#include <tree_project_frame.h> +#include <online_help.h> +#include <wildcards_and_files_ext.h> +#include <boost/ptr_container/ptr_vector.hpp> +#include <hotkeys_basic.h> + +#include <build_version.h> + + +// a dummy to quiet linking with EDA_BASE_FRAME::config(); +#include <kiface_i.h> +KIFACE_I& Kiface() +{ + // This function should never be called. It is only referenced from + // EDA_BASE_FRAME::config() and this is only provided to satisfy the linker, + // not to be actually called. + wxLogFatalError( wxT( "Unexpected call to Kiface() in kicad/kicad.cpp" ) ); + + return (KIFACE_I&) *(KIFACE_I*) 0; +} + +static PGM_KICAD program; + +PGM_KICAD& Pgm() +{ + return program; +} + + +bool PGM_KICAD::OnPgmInit( wxApp* aWxApp ) +{ + m_wx_app = aWxApp; // first thing. + + wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath(); + + if( !wxIsAbsolutePath( absoluteArgv0 ) ) + { + wxLogError( wxT( "No meaningful argv[0]" ) ); + return false; + } + + if( !initPgm() ) + return false; + + m_bm.Init(); + + // Add search paths to feed the PGM_KICAD::SysSearch() function, + // currenly limited in support to only look for project templates + { + SEARCH_STACK bases; + + SystemDirsAppend( &bases ); + + // DBG( bases.Show( (std::string(__func__) + " bases").c_str() );) + + for( unsigned i = 0; i < bases.GetCount(); ++i ) + { + wxFileName fn( bases[i], wxEmptyString ); + + // Add KiCad template file path to search path list. + fn.AppendDir( wxT( "template" ) ); + m_bm.m_search.AddPaths( fn.GetPath() ); + } + + //DBG( m_bm.m_search.Show( (std::string( __func__ ) + " SysSearch()").c_str() );) + } + + // Must be called before creating the main frame in order to + // display the real hotkeys in menus or tool tips + extern struct EDA_HOTKEY_CONFIG kicad_Manager_Hokeys_Descr[]; + ReadHotkeyConfig( KICAD_MANAGER_FRAME_NAME, kicad_Manager_Hokeys_Descr ); + + KICAD_MANAGER_FRAME* frame = new KICAD_MANAGER_FRAME( NULL, wxT( "KiCad" ), + wxDefaultPosition, wxDefaultSize ); + App().SetTopWindow( frame ); + + Kiway.SetTop( frame ); + + bool prjloaded = false; // true when the project is loaded + + if( App().argc > 1 ) + frame->SetProjectFileName( App().argv[1] ); + + else if( GetFileHistory().GetCount() ) + { + wxString last_pro = GetFileHistory().GetHistoryFile( 0 ); + + if( !wxFileExists( last_pro ) ) + { + GetFileHistory().RemoveFileFromHistory( 0 ); + + wxFileName namelessProject( wxStandardPaths::Get().GetDocumentsDir(), NAMELESS_PROJECT, + ProjectFileExtension ); + + frame->SetProjectFileName( namelessProject.GetFullPath() ); + } + else + { + // Try to open the last opened project, + // if a project name is not given when starting Kicad + frame->SetProjectFileName( last_pro ); + + wxCommandEvent cmd( 0, wxID_FILE1 ); + + frame->OnFileHistory( cmd ); + prjloaded = true; // OnFileHistory() loads the project + } + } + else // there is no history + { + wxFileName namelessProject( wxStandardPaths::Get().GetDocumentsDir(), NAMELESS_PROJECT, + ProjectFileExtension ); + + frame->SetProjectFileName( namelessProject.GetFullPath() ); + } + + if( !prjloaded ) + { + wxCommandEvent cmd( 0, wxID_ANY ); + + frame->OnLoadProject( cmd ); + } + + frame->Show( true ); + frame->Raise(); + + return true; +} + + +void PGM_KICAD::OnPgmExit() +{ + Kiway.OnKiwayEnd(); + + saveCommonSettings(); + + // write common settings to disk, and destroy everything in PGM_KICAD, + // especially wxSingleInstanceCheckerImpl earlier than wxApp and earlier + // than static destruction would. + destroy(); +} + + +void PGM_KICAD::MacOpenFile( const wxString& aFileName ) +{ +#if defined(__WXMAC__) + + KICAD_MANAGER_FRAME* frame = (KICAD_MANAGER_FRAME*) App().GetTopWindow(); + + frame->SetProjectFileName( aFileName ); + + wxCommandEvent loadEvent( 0, wxID_ANY ); + + frame->OnLoadProject( loadEvent ); +#endif +} + + +void PGM_KICAD::destroy() +{ + // unlike a normal destructor, this is designed to be called more + // than once safely: + + m_bm.End(); + + PGM_BASE::destroy(); +} + + +KIWAY Kiway( &Pgm(), KFCTL_CPP_PROJECT_SUITE ); + + +/** + * Struct APP_KICAD + * is not publicly visible because most of the action is in PGM_KICAD these days. + */ +struct APP_KICAD : public wxApp +{ +#if defined (__LINUX__) + APP_KICAD(): wxApp() + { + // Disable proxy menu in Unity window manager. Only usual menubar works with wxWidgets (at least <= 3.1) + // When the proxy menu menubar is enable, some important things for us do not work: menuitems UI events and shortcuts. + wxString wm; + + if( wxGetEnv( wxT( "XDG_CURRENT_DESKTOP" ), &wm ) && wm.CmpNoCase( wxT( "Unity" ) ) == 0 ) + { + wxSetEnv ( wxT("UBUNTU_MENUPROXY" ), wxT( "0" ) ); + } + } +#endif + + bool OnInit() // overload wxApp virtual + { + // if( Kiways.OnStart( this ) ) + { + return Pgm().OnPgmInit( this ); + } + return false; + } + + int OnExit() // overload wxApp virtual + { + // Kiways.OnEnd(); + + Pgm().OnPgmExit(); + + return wxApp::OnExit(); + } + + int OnRun() // overload wxApp virtual + { + try + { + return wxApp::OnRun(); + } + catch( const std::exception& e ) + { + wxLogError( wxT( "Unhandled exception class: %s what: %s" ), + GetChars( FROM_UTF8( typeid(e).name() )), + GetChars( FROM_UTF8( e.what() ) ) ); + } + catch( const IO_ERROR& ioe ) + { + wxLogError( GetChars( ioe.errorText ) ); + } + catch(...) + { + wxLogError( wxT( "Unhandled exception of unknown type" ) ); + } + + return -1; + } + + /** + * Function MacOpenFile + * is specific to MacOSX (not used under Linux or Windows). + * MacOSX requires it for file association. + * @see http://wiki.wxwidgets.org/WxMac-specific_topics + */ + void MacOpenFile( const wxString& aFileName ) // overload wxApp virtual + { + Pgm().MacOpenFile( aFileName ); + } +}; + +IMPLEMENT_APP( APP_KICAD ); + + +// The C++ project manager supports one open PROJECT, so Prj() calls within +// this link image need this function. +PROJECT& Prj() +{ + return Kiway.Prj(); +} + + +#if 0 // there can be only one in C++ project manager. + +bool KIWAY_MGR::OnStart( wxApp* aProcess ) +{ + // The C++ project manager supports only one open PROJECT + // We should need no copy constructor for KIWAY to push a pointer. + m_kiways.push_back( new KIWAY() ); + + return true; +} + + +void KIWAY_MGR::OnEnd() +{ +} + +#endif diff --git a/kicad/kicad.h b/kicad/kicad.h new file mode 100644 index 0000000..aa98820 --- /dev/null +++ b/kicad/kicad.h @@ -0,0 +1,337 @@ +/** + * @file kicad/kicad.h + * @brief KICAD_MANAGER_FRAME is the KiCad main frame. + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN (www.cern.ch) + * Copyright (C) 2015 KiCad Developers, see CHANGELOG.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 + */ + +#ifndef KICAD_H +#define KICAD_H + +#include <vector> + +#include <wx/treectrl.h> +#include <wx/dragimag.h> +#include <wx/filename.h> +#include <wx/process.h> + +#include <id.h> +#include <wxstruct.h> + +#define KICAD_MANAGER_FRAME_NAME wxT( "KicadFrame" ) + +class LAUNCHER_PANEL; +class TREEPROJECTFILES; +class TREE_PROJECT_FRAME; + +// Enum to identify the type of files handled by Kicad manager +// +// When changing this enum please verify (and perhaps update) +// TREE_PROJECT_FRAME::GetFileExt(), +// s_AllowedExtensionsToList[] + +enum TreeFileType { + TREE_PROJECT = 1, + TREE_SCHEMA, // Schematic file (.sch) + TREE_LEGACY_PCB, // board file (.brd) legacy format + TREE_SEXP_PCB, // board file (.kicad_brd) new s expression format + TREE_GERBER, // Gerber file (.pho, .g*) + TREE_HTML, // HTML file (.htm, *.html) + TREE_PDF, // PDF file (.pdf) + TREE_TXT, // ascii text file (.txt) + TREE_NET, // netlist file (.net) + TREE_UNKNOWN, + TREE_DIRECTORY, + TREE_CMP_LINK, // cmp/footprint link file (.cmp) + TREE_REPORT, // report file (.rpt) + TREE_FP_PLACE, // fooprints position (place) file (.pos) + TREE_DRILL, // Excellon drill file (.drl) + TREE_SVG, // SVG file (.svg) + TREE_PAGE_LAYOUT_DESCR, // Page layout and title block descr file (.kicad_wks) + TREE_FOOTPRINT_FILE, // footprint file (.kicad_mod) + TREE_SCHEMATIC_LIBFILE, // schematic library file (.lib) + TREE_MAX +}; + + +/** + * Command IDs for KiCad. + * + * Please add IDs that are unique to Kicad here and not in the global id.h file. + * This will prevent the entire project from being rebuilt when adding + * new commands to KiCad. + * + * However, now the Kicad manager and other sub applications are running inside + * the same application, these IDs are kept unique inside the whole Kicad code + * See the global id.h which reserves room for the Kicad manager IDs + * and expand this room if needed + * + * We have experienced issues with duplicate menus IDs between frames + * because wxUpdateUIEvent events are sent to parent frames, when a wxUpdateUIEvent + * event function does not exists for some menuitems ID, and therefore + * with duplicate menuitems IDs in different frames, the wrong menuitem can be used + * by a function called by the wxUpdateUIEvent event loop. + * + * The number of items in this list should be less than ROOM_FOR_KICADMANAGER (see id.h) + */ + +enum id_kicad_frm { + ID_LEFT_FRAME = ID_KICAD_MANAGER_START, + ID_PROJECT_TREE, + ID_PROJECT_TXTEDIT, + ID_PROJECT_TREE_REFRESH, + ID_PROJECT_NEWDIR, + ID_PROJECT_DELETE, + ID_PROJECT_RENAME, + ID_PROJECT_OPEN_FILE_WITH_TEXT_EDITOR, + + ID_TO_SCH, + ID_TO_SCH_LIB_EDITOR, + ID_TO_PCB, + ID_TO_PCB_FP_EDITOR, + ID_TO_CVPCB, + ID_TO_GERBVIEW, + ID_TO_BITMAP_CONVERTER, + ID_TO_PCB_CALCULATOR, + ID_TO_PL_EDITOR, + + ID_TO_TEXT_EDITOR, + ID_BROWSE_AN_SELECT_FILE, + ID_SELECT_PREFERED_EDITOR, + ID_SELECT_PREFERED_PDF_BROWSER_NAME, + ID_SELECT_PREFERED_PDF_BROWSER, + ID_SELECT_DEFAULT_PDF_BROWSER, + ID_SAVE_AND_ZIP_FILES, + ID_READ_ZIP_ARCHIVE, + ID_INIT_WATCHED_PATHS, + + // Please, verify: the number of items in this list should be + // less than ROOM_FOR_KICADMANAGER (see id.h) + ID_KICADMANAGER_END_LIST +}; + + +/** + * Class KICAD_MANAGER_FRAME + * is the main KiCad project manager frame. It is not a KIWAY_PLAYER. + */ +class KICAD_MANAGER_FRAME : public EDA_BASE_FRAME +{ +public: + KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title, + const wxPoint& pos, const wxSize& size ); + + ~KICAD_MANAGER_FRAME(); + + void OnCloseWindow( wxCloseEvent& Event ); + void OnSize( wxSizeEvent& event ); + + /** + * Function OnLoadProject + * loads an exiting or creates a new project (.pro) file. + */ + void OnLoadProject( wxCommandEvent& event ); + + /** + * Function OnCreateProjectFromTemplate + * Creates a new project folder, copy a template into this new folder. + * and open this new projrct as working project + */ + void OnCreateProjectFromTemplate( wxCommandEvent& event ); + + /** + * Function OnSaveProject + * is the command event hendler to Save the project (.pro) file containing the top level + * configuration parameters. + */ + void OnSaveProject( wxCommandEvent& event ); + + void OnArchiveFiles( wxCommandEvent& event ); + void OnUnarchiveFiles( wxCommandEvent& event ); + + void OnRunEeschema( wxCommandEvent& event ); + void OnRunSchLibEditor( wxCommandEvent& event ); + void OnRunPcbNew( wxCommandEvent& event ); + void OnRunPcbFpEditor( wxCommandEvent& event ); + void OnRunGerbview( wxCommandEvent& event ); + void OnRunBitmapConverter( wxCommandEvent& event ); + void OnRunPcbCalculator( wxCommandEvent& event ); + void OnRunPageLayoutEditor( wxCommandEvent& event ); + + void OnConfigurePaths( wxCommandEvent& aEvent ); + void OnOpenTextEditor( wxCommandEvent& event ); + void OnOpenFileInTextEditor( wxCommandEvent& event ); + void OnOpenFileInEditor( wxCommandEvent& event ); + + void OnFileHistory( wxCommandEvent& event ); + void OnExit( wxCommandEvent& event ); + void Process_Preferences( wxCommandEvent& event ); + + void Process_Config( wxCommandEvent& event ); + + void ReCreateMenuBar(); + void RecreateBaseHToolbar(); + + /** + * Function PrintMsg + * displays \a aText in the text panel. + * + * @param aText The text to display. + */ + void PrintMsg( const wxString& aText ); + + /** + * a minor helper function: + * Prints the Current Working Dir name and the projet name on the text panel. + */ + void PrintPrjInfo(); + + /** + * a minor helper function: + * Erase the text panel. + */ + void ClearMsg(); + + void OnRefresh( wxCommandEvent& event ); + void OnSelectDefaultPdfBrowser( wxCommandEvent& event ); + void OnSelectPreferredPdfBrowser( wxCommandEvent& event ); + + void OnUpdateDefaultPdfBrowser( wxUpdateUIEvent& event ); + void OnUpdatePreferredPdfBrowser( wxUpdateUIEvent& event ); + void OnUpdateRequiresProject( wxUpdateUIEvent& event ); + + void CreateNewProject( const wxString& aPrjFullFileName, bool aTemplateSelector ); + + void LoadSettings( wxConfigBase* aCfg ); + + void SaveSettings( wxConfigBase* aCfg ); + + /** + * Function Execute + * opens another KiCad application and logs a message. + * @param frame = owner frame. + * @param execFile = name of the executable file. + * @param param = parameters to be passed to the executable. + */ + void Execute( wxWindow* frame, const wxString& execFile, + wxString param = wxEmptyString ); + + class TERMINATE_HANDLER : public wxProcess + { + private: + wxString appName; + + public: + TERMINATE_HANDLER( const wxString& appName ) : + appName(appName) + { + } + + void OnTerminate( int pid, int status ); + }; + + /** + * Called by sending a event with id = ID_INIT_WATCHED_PATHS + * rebuild the list of wahtched paths + */ + void OnChangeWatchedPaths(wxCommandEvent& aEvent ); + + + void SetProjectFileName( const wxString& aFullProjectProFileName ); + const wxString GetProjectFileName(); + + // read only accessors + const wxString SchFileName(); + const wxString PcbFileName(); + const wxString PcbLegacyFileName(); + + void ReCreateTreePrj(); + + /// Call this only for a PCB associated with the current project. That is, + /// it must have the same path and name as the project *.pro file. + void RunPcbNew( const wxString& aProjectBoardFileName ); + + /// Call this only for a SCH associated with the current project. That is, + /// it must have the same path and name as the project *.pro file. + void RunEeschema( const wxString& aProjectSchematicFileName ); + + DECLARE_EVENT_TABLE() + +private: + + wxConfigBase* config(); // override EDA_BASE_FRAME virtual + + const SEARCH_STACK& sys_search(); // override EDA_BASE_FRAME virtual + + wxString help_name(); // override EDA_BASE_FRAME virtual + + TREE_PROJECT_FRAME* m_LeftWin; + LAUNCHER_PANEL* m_Launcher; + wxTextCtrl* m_MessagesBox; + wxAuiToolBar* m_VToolBar; // Vertical toolbar (not used) + + int m_leftWinWidth; + EDA_HOTKEY_CONFIG* m_manager_Hokeys_Descr; + + void language_change( wxCommandEvent& event ); + + bool m_active_project; +}; + + +/** class LAUNCHER_PANEL + */ +class LAUNCHER_PANEL : public wxPanel +{ +private: + int m_buttonSeparation; // button distance in pixels + wxPoint m_buttonsListPosition; /* position of the left bottom corner + * of the first bitmap button + */ + wxPoint m_buttonLastPosition; // position of the last button in the window + int m_bitmapButtons_maxHeigth; // height of bigger bitmap buttons + // Used to calculate the height of the panel. + +public: LAUNCHER_PANEL( wxWindow* parent ); + ~LAUNCHER_PANEL() { }; + + int GetPanelHeight() const; + +private: + + /** + * Function CreateCommandToolbar + * creates the main tool bar buttons (fast launch buttons) + */ + void CreateCommandToolbar( void ); + + wxBitmapButton* AddBitmapButton( wxWindowID aId, const wxBitmap& aBitmap ); +}; + +// The C++ project manager includes a single PROJECT in its link image. +class PROJECT; +extern PROJECT& Prj(); + +#endif diff --git a/kicad/kicad.icns b/kicad/kicad.icns Binary files differnew file mode 100644 index 0000000..01307df --- /dev/null +++ b/kicad/kicad.icns diff --git a/kicad/kicad.rc b/kicad/kicad.rc new file mode 100644 index 0000000..578d82c --- /dev/null +++ b/kicad/kicad.rc @@ -0,0 +1,3 @@ +icon_kicad ICON "../bitmaps_png/icons/icon_kicad.ico" + +#include "wx/msw/wx.rc" diff --git a/kicad/kicad_doc.icns b/kicad/kicad_doc.icns Binary files differnew file mode 100644 index 0000000..b877d8c --- /dev/null +++ b/kicad/kicad_doc.icns diff --git a/kicad/logokicad.png b/kicad/logokicad.png Binary files differnew file mode 100644 index 0000000..a7e5f82 --- /dev/null +++ b/kicad/logokicad.png diff --git a/kicad/mainframe.cpp b/kicad/mainframe.cpp new file mode 100644 index 0000000..df0122a --- /dev/null +++ b/kicad/mainframe.cpp @@ -0,0 +1,547 @@ +/** + * @file kicad/mainframe.cpp + * @brief KICAD_MANAGER_FRAME is the KiCad main frame. + */ + +/* + * 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) 2013 CERN (www.cern.ch) + * 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 + */ + +#include <fctsys.h> +#include <pgm_kicad.h> +#include <draw_frame.h> +#include <kiway.h> +#include <kiway_player.h> +#include <confirm.h> +#include <gestfich.h> +#include <macros.h> + +#include <kicad.h> +#include <tree_project_frame.h> +#include <wildcards_and_files_ext.h> +#include <menus_helpers.h> +#include <dialog_hotkeys_editor.h> + +#include <wx/filefn.h> + + +#define TREE_FRAME_WIDTH_ENTRY wxT( "LeftWinWidth" ) + +KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, + const wxString& title, const wxPoint& pos, const wxSize& size ) : + EDA_BASE_FRAME( parent, KICAD_MAIN_FRAME_T, title, pos, size, + KICAD_DEFAULT_DRAWFRAME_STYLE, KICAD_MANAGER_FRAME_NAME ) +{ + m_active_project = false; + m_leftWinWidth = 60; + m_manager_Hokeys_Descr = NULL; + + // Create the status line (bottom of the frame + static const int dims[3] = { -1, -1, 100 }; + + CreateStatusBar( 3 ); + SetStatusWidths( 3, dims ); + + // Give an icon + wxIcon icon; + icon.CopyFromBitmap( KiBitmap( icon_kicad_xpm ) ); + SetIcon( icon ); + + // Give the last sise and pos to main window + LoadSettings( config() ); + SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); + + // Left window: is the box which display tree project + m_LeftWin = new TREE_PROJECT_FRAME( this ); + + // Right top Window: buttons to launch applications + m_Launcher = new LAUNCHER_PANEL( this ); + + // Add the wxTextCtrl showing all messages from KiCad: + m_MessagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY ); + + RecreateBaseHToolbar(); + ReCreateMenuBar(); + + m_auimgr.SetManagedWindow( this ); + + EDA_PANEINFO horiztb; + horiztb.HorizontalToolbarPane(); + + EDA_PANEINFO info; + info.InfoToolbarPane(); + + m_auimgr.AddPane( m_mainToolBar, + wxAuiPaneInfo( horiztb ).Name( wxT( "m_mainToolBar" ) ).Top() ); + + m_auimgr.AddPane( m_LeftWin, + wxAuiPaneInfo(info).Name( wxT( "m_LeftWin" ) ).Left(). + BestSize( m_leftWinWidth, -1 ). + Layer( 1 ) ); + + m_auimgr.AddPane( m_Launcher, wxTOP ); + m_auimgr.GetPane( m_Launcher).CaptionVisible( false ).Row(1) + .BestSize( -1, m_Launcher->GetPanelHeight() ).PaneBorder( false ).Resizable( false ); + + m_auimgr.AddPane( m_MessagesBox, + wxAuiPaneInfo().Name( wxT( "m_MessagesBox" ) ).CentrePane().Layer( 2 ) ); + + m_auimgr.GetPane( m_LeftWin ).MinSize( wxSize( 80, -1) ); + m_auimgr.GetPane( m_LeftWin ).BestSize(wxSize(m_leftWinWidth, -1) ); + + m_auimgr.Update(); +} + + +KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME() +{ + m_auimgr.UnInit(); +} + + +wxConfigBase* KICAD_MANAGER_FRAME::config() +{ + wxConfigBase* ret = Pgm().PgmSettings(); + wxASSERT( ret ); + return ret; +} + + +void KICAD_MANAGER_FRAME::SetProjectFileName( const wxString& aFullProjectProFileName ) +{ + // ensure file name is absolute: + wxFileName fn( aFullProjectProFileName ); + + if( !fn.IsAbsolute() ) + fn.MakeAbsolute(); + + Prj().SetProjectFullName( fn.GetFullPath() ); +} + + +const wxString KICAD_MANAGER_FRAME::GetProjectFileName() +{ + return Prj().GetProjectFullName(); +} + + +const wxString KICAD_MANAGER_FRAME::SchFileName() +{ + wxFileName fn( GetProjectFileName() ); + + fn.SetExt( SchematicFileExtension ); + + return fn.GetFullPath(); +} + + +const wxString KICAD_MANAGER_FRAME::PcbFileName() +{ + wxFileName fn( GetProjectFileName() ); + + fn.SetExt( PcbFileExtension ); + + return fn.GetFullPath(); +} + + +const wxString KICAD_MANAGER_FRAME::PcbLegacyFileName() +{ + wxFileName fn( GetProjectFileName() ); + + fn.SetExt( LegacyPcbFileExtension ); + + return fn.GetFullPath(); +} + + +void KICAD_MANAGER_FRAME::ReCreateTreePrj() +{ + m_LeftWin->ReCreateTreePrj(); +} + + +const SEARCH_STACK& KICAD_MANAGER_FRAME::sys_search() +{ + return Pgm().SysSearch(); +} + + +wxString KICAD_MANAGER_FRAME::help_name() +{ + return Pgm().GetHelpFileName(); +} + + +void KICAD_MANAGER_FRAME::PrintMsg( const wxString& aText ) +{ + m_MessagesBox->AppendText( aText ); +} + + +void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event ) +{ + if( m_auimgr.GetManagedWindow() ) + m_auimgr.Update(); + + event.Skip(); +} + + +void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event ) +{ + if( Kiway.PlayersClose( false ) ) + { + int px, py; + + UpdateFileHistory( GetProjectFileName(), &Pgm().GetFileHistory() ); + + if( !IsIconized() ) // save main frame position and size + { + GetPosition( &px, &py ); + m_FramePos.x = px; + m_FramePos.y = py; + + GetSize( &px, &py ); + m_FrameSize.x = px; + m_FrameSize.y = py; + } + + Event.SetCanVeto( true ); + + m_LeftWin->Show( false ); + + Destroy(); + } +} + + +void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event ) +{ + Close( true ); +} + + +void KICAD_MANAGER_FRAME::TERMINATE_HANDLER::OnTerminate( int pid, int status ) +{ + wxString msg = wxString::Format( _( "%s closed [pid=%d]\n" ), + GetChars( appName ), pid ); + + wxWindow* window = wxWindow::FindWindowByName( KICAD_MANAGER_FRAME_NAME ); + + if( window ) // Should always happen. + { + // Be sure the kicad frame manager is found + // This dynamic cast is not really mandatory, but ... + KICAD_MANAGER_FRAME* frame = dynamic_cast<KICAD_MANAGER_FRAME*> (window); + + if( frame ) + frame->PrintMsg( msg ); + } + + delete this; +} + + +void KICAD_MANAGER_FRAME::Execute( wxWindow* frame, const wxString& execFile, + wxString params ) +{ + if( params.size() ) + AddDelimiterString( params ); + + TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile ); + + long pid = ExecuteFile( frame, execFile, params, callback ); + + if( pid > 0 ) + { + wxString msg = wxString::Format( _( "%s %s opened [pid=%ld]\n" ), + GetChars( execFile ), GetChars( params ), pid ); + + PrintMsg( msg ); + } + else + { + delete callback; + } +} + + +void KICAD_MANAGER_FRAME::RunEeschema( const wxString& aProjectSchematicFileName ) +{ + KIWAY_PLAYER* frame = Kiway.Player( FRAME_SCH, false ); + + // Please: note: DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers() calls + // Kiway.Player( FRAME_SCH, true ) + // therefore, the schematic editor is sometimes running, but the schematic project + // is not loaded, if the library editor was called, and the dialog field editor was used. + // On linux, it happens the first time the schematic editor is launched, if + // library editor was running, and the dialog field editor was open + // On Windows, it happens always after the library editor was called, + // and the dialog field editor was used + if( !frame ) + { + frame = Kiway.Player( FRAME_SCH, true ); + } + + if( !frame->IsShown() ) // the frame exists, (created by the dialog field editor) + // but no project loaded. + { + frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectSchematicFileName ) ); + frame->Show( true ); + } + + // On Windows, Raise() does not bring the window on screen, when iconized or not shown + // On linux, Raise() brings the window on screen, but this code works fine + if( frame->IsIconized() ) + frame->Iconize( false ); + + frame->Raise(); +} + + +void KICAD_MANAGER_FRAME::OnRunEeschema( wxCommandEvent& event ) +{ + wxFileName fn( GetProjectFileName() ); + fn.SetExt( SchematicFileExtension ); + RunEeschema( fn.GetFullPath() ); +} + + +void KICAD_MANAGER_FRAME::OnRunSchLibEditor( wxCommandEvent& event ) +{ + KIWAY_PLAYER* frame = Kiway.Player( FRAME_SCH_LIB_EDITOR, false ); + + if( !frame ) + { + frame = Kiway.Player( FRAME_SCH_LIB_EDITOR, true ); + // frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectSchematicFileName ) ); + frame->Show( true ); + } + + // On Windows, Raise() does not bring the window on screen, when iconized + if( frame->IsIconized() ) + frame->Iconize( false ); + + frame->Raise(); +} + + +void KICAD_MANAGER_FRAME::RunPcbNew( const wxString& aProjectBoardFileName ) +{ + KIWAY_PLAYER* frame = Kiway.Player( FRAME_PCB, true ); + + // a pcb frame can be already existing, but not yet used. + // this is the case when running the footprint editor, or the footprint viewer first + // if the frame is not visible, the board is not yet loaded + if( !frame->IsVisible() ) + { + frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectBoardFileName ) ); + frame->Show( true ); + } + + // On Windows, Raise() does not bring the window on screen, when iconized + if( frame->IsIconized() ) + frame->Iconize( false ); + + frame->Raise(); +} + + +void KICAD_MANAGER_FRAME::OnRunPcbNew( wxCommandEvent& event ) +{ + wxFileName kicad_board( PcbFileName() ); + wxFileName legacy_board( PcbLegacyFileName() ); + + wxFileName& board = ( !legacy_board.FileExists() || kicad_board.FileExists() ) ? + kicad_board : legacy_board; + + RunPcbNew( board.GetFullPath() ); +} + + +void KICAD_MANAGER_FRAME::OnRunPcbFpEditor( wxCommandEvent& event ) +{ + KIWAY_PLAYER* frame = Kiway.Player( FRAME_PCB_MODULE_EDITOR, false ); + + if( !frame ) + { + frame = Kiway.Player( FRAME_PCB_MODULE_EDITOR, true ); +// frame->OpenProjectFiles( std::vector<wxString>( 1, aProjectBoardFileName ) ); + frame->Show( true ); + } + + // On Windows, Raise() does not bring the window on screen, when iconized + if( frame->IsIconized() ) + frame->Iconize( false ); + + frame->Raise(); +} + + +void KICAD_MANAGER_FRAME::OnRunBitmapConverter( wxCommandEvent& event ) +{ + Execute( this, BITMAPCONVERTER_EXE ); +} + + +void KICAD_MANAGER_FRAME::OnRunPcbCalculator( wxCommandEvent& event ) +{ + Execute( this, PCB_CALCULATOR_EXE ); +} + + +void KICAD_MANAGER_FRAME::OnRunPageLayoutEditor( wxCommandEvent& event ) +{ + Execute( this, PL_EDITOR_EXE ); +} + + + +void KICAD_MANAGER_FRAME::OnRunGerbview( wxCommandEvent& event ) +{ + // Gerbview is called without any file to open, because we do not know + // the list and the name of files to open (if any...). + // however we run it in the path of the project + Execute( this, GERBVIEW_EXE, Prj().GetProjectPath() ); +} + + +void KICAD_MANAGER_FRAME::OnOpenTextEditor( wxCommandEvent& event ) +{ + wxString editorname = Pgm().GetEditorName(); + + if( !editorname.IsEmpty() ) + Execute( this, editorname, wxEmptyString ); +} + + +void KICAD_MANAGER_FRAME::OnOpenFileInTextEditor( wxCommandEvent& event ) +{ + wxString mask( wxT( "*" ) ); + +#ifdef __WINDOWS__ + mask += wxT( ".*" ); +#endif + + mask = _( "Text file (" ) + mask + wxT( ")|" ) + mask; + wxString default_dir = Prj().GetProjectPath(); + + wxFileDialog dlg( this, _( "Load File to Edit" ), default_dir, + wxEmptyString, mask, wxFD_OPEN ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + wxString filename = wxT( "\"" ); + filename += dlg.GetPath() + wxT( "\"" ); + + if( !dlg.GetPath().IsEmpty() && !Pgm().GetEditorName().IsEmpty() ) + Execute( this, Pgm().GetEditorName(), filename ); +} + + +void KICAD_MANAGER_FRAME::OnRefresh( wxCommandEvent& event ) +{ + m_LeftWin->ReCreateTreePrj(); +} + + +void KICAD_MANAGER_FRAME::language_change( wxCommandEvent& event ) +{ + int id = event.GetId(); + + Kiway.SetLanguage( id ); +} + + +void KICAD_MANAGER_FRAME::ClearMsg() +{ + m_MessagesBox->Clear(); +} + + +void KICAD_MANAGER_FRAME::LoadSettings( wxConfigBase* aCfg ) +{ + EDA_BASE_FRAME::LoadSettings( aCfg ); + aCfg->Read( TREE_FRAME_WIDTH_ENTRY, &m_leftWinWidth ); +} + + +void KICAD_MANAGER_FRAME::SaveSettings( wxConfigBase* aCfg ) +{ + EDA_BASE_FRAME::SaveSettings( aCfg ); + aCfg->Write( TREE_FRAME_WIDTH_ENTRY, m_LeftWin->GetSize().x ); +} + + +/** + * a minor helper function: + * Prints the Current Project full name on the text panel. + */ +void KICAD_MANAGER_FRAME::PrintPrjInfo() +{ + wxString msg = wxString::Format( _( "Project name:\n%s\n" ), + GetChars( GetProjectFileName() ) ); + PrintMsg( msg ); +} + +void KICAD_MANAGER_FRAME::Process_Config( wxCommandEvent& event ) +{ + int id = event.GetId(); + wxFileName fn; + + switch( id ) + { + // Hotkey IDs + case ID_PREFERENCES_HOTKEY_SHOW_EDITOR: + InstallHotkeyFrame( this, m_manager_Hokeys_Descr ); + break; + + case ID_PREFERENCES_HOTKEY_EXPORT_CONFIG: + ExportHotkeyConfigToFile( m_manager_Hokeys_Descr, wxT( "kicad" ) ); + break; + + case ID_PREFERENCES_HOTKEY_IMPORT_CONFIG: + ImportHotkeyConfigFromFile( m_manager_Hokeys_Descr, wxT( "kicad" ) ); + break; + + case ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST: + // Display current hotkey list for LibEdit. + DisplayHotkeyList( this, m_manager_Hokeys_Descr ); + break; + + default: + wxFAIL_MSG( wxT( "KICAD_MANAGER_FRAME::Process_Config error" ) ); + break; + } +} + + +void KICAD_MANAGER_FRAME::OnConfigurePaths( wxCommandEvent& aEvent ) +{ + Pgm().ConfigurePaths( this ); +} diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp new file mode 100644 index 0000000..130b661 --- /dev/null +++ b/kicad/menubar.cpp @@ -0,0 +1,501 @@ +/* + * 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) 2009-2015 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.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 kicad/menubar.cpp + * @brief (Re)Create the project manager menubar for KiCad + */ +#include <fctsys.h> +#include <pgm_kicad.h> +#include <kicad.h> +#include <menus_helpers.h> +#include <tree_project_frame.h> +#include <hotkeys_basic.h> + +// Menubar and toolbar event table +BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME ) + // Window events + EVT_SIZE( KICAD_MANAGER_FRAME::OnSize ) + EVT_CLOSE( KICAD_MANAGER_FRAME::OnCloseWindow ) + + // Toolbar events + EVT_TOOL( ID_NEW_PROJECT, KICAD_MANAGER_FRAME::OnLoadProject ) + EVT_TOOL( ID_NEW_PROJECT_FROM_TEMPLATE, KICAD_MANAGER_FRAME::OnCreateProjectFromTemplate ) + EVT_TOOL( ID_LOAD_PROJECT, KICAD_MANAGER_FRAME::OnLoadProject ) + + // Menu events + EVT_MENU( ID_SAVE_PROJECT, KICAD_MANAGER_FRAME::OnSaveProject ) + EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit ) + EVT_MENU( ID_TO_TEXT_EDITOR, KICAD_MANAGER_FRAME::OnOpenTextEditor ) + EVT_MENU( ID_BROWSE_AN_SELECT_FILE, KICAD_MANAGER_FRAME::OnOpenFileInTextEditor ) + EVT_MENU( ID_PREFERENCES_CONFIGURE_PATHS, KICAD_MANAGER_FRAME::OnConfigurePaths ) + EVT_MENU( ID_SELECT_PREFERED_EDITOR, EDA_BASE_FRAME::OnSelectPreferredEditor ) + EVT_MENU( ID_SELECT_DEFAULT_PDF_BROWSER, KICAD_MANAGER_FRAME::OnSelectDefaultPdfBrowser ) + EVT_MENU( ID_SELECT_PREFERED_PDF_BROWSER, KICAD_MANAGER_FRAME::OnSelectPreferredPdfBrowser ) + EVT_MENU( ID_SELECT_PREFERED_PDF_BROWSER_NAME, + KICAD_MANAGER_FRAME::OnSelectPreferredPdfBrowser ) + EVT_MENU( ID_SAVE_AND_ZIP_FILES, KICAD_MANAGER_FRAME::OnArchiveFiles ) + EVT_MENU( ID_READ_ZIP_ARCHIVE, KICAD_MANAGER_FRAME::OnUnarchiveFiles ) + EVT_MENU( ID_PROJECT_TREE_REFRESH, KICAD_MANAGER_FRAME::OnRefresh ) + EVT_MENU( wxID_HELP, KICAD_MANAGER_FRAME::GetKicadHelp ) + EVT_MENU( wxID_INDEX, KICAD_MANAGER_FRAME::GetKicadHelp ) + EVT_MENU( wxID_ABOUT, KICAD_MANAGER_FRAME::GetKicadAbout ) + + // Range menu events + EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::language_change ) + + EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, KICAD_MANAGER_FRAME::OnFileHistory ) + + // Hotkey management (show list, edit ...) events + EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, + KICAD_MANAGER_FRAME::Process_Config ) + + + // Special functions + EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths ) + + // Button events (in command frame), and menu events equivalent to buttons + EVT_BUTTON( ID_TO_SCH, KICAD_MANAGER_FRAME::OnRunEeschema ) + EVT_MENU( ID_TO_SCH, KICAD_MANAGER_FRAME::OnRunEeschema ) + + EVT_BUTTON( ID_TO_SCH_LIB_EDITOR, KICAD_MANAGER_FRAME::OnRunSchLibEditor ) + EVT_MENU( ID_TO_SCH_LIB_EDITOR, KICAD_MANAGER_FRAME::OnRunSchLibEditor ) + + EVT_BUTTON( ID_TO_PCB, KICAD_MANAGER_FRAME::OnRunPcbNew ) + EVT_MENU( ID_TO_PCB, KICAD_MANAGER_FRAME::OnRunPcbNew ) + + EVT_BUTTON( ID_TO_PCB_FP_EDITOR, KICAD_MANAGER_FRAME::OnRunPcbFpEditor ) + EVT_MENU( ID_TO_PCB_FP_EDITOR, KICAD_MANAGER_FRAME::OnRunPcbFpEditor ) + + EVT_BUTTON( ID_TO_GERBVIEW, KICAD_MANAGER_FRAME::OnRunGerbview ) + EVT_MENU( ID_TO_GERBVIEW, KICAD_MANAGER_FRAME::OnRunGerbview ) + + EVT_BUTTON( ID_TO_BITMAP_CONVERTER, KICAD_MANAGER_FRAME::OnRunBitmapConverter ) + EVT_MENU( ID_TO_BITMAP_CONVERTER, KICAD_MANAGER_FRAME::OnRunBitmapConverter ) + + EVT_BUTTON( ID_TO_PCB_CALCULATOR, KICAD_MANAGER_FRAME::OnRunPcbCalculator ) + EVT_MENU( ID_TO_PCB_CALCULATOR, KICAD_MANAGER_FRAME::OnRunPcbCalculator ) + + EVT_BUTTON( ID_TO_PL_EDITOR, KICAD_MANAGER_FRAME::OnRunPageLayoutEditor ) + EVT_MENU( ID_TO_PL_EDITOR, KICAD_MANAGER_FRAME::OnRunPageLayoutEditor ) + + EVT_UPDATE_UI( ID_SELECT_DEFAULT_PDF_BROWSER, KICAD_MANAGER_FRAME::OnUpdateDefaultPdfBrowser ) + EVT_UPDATE_UI( ID_SELECT_PREFERED_PDF_BROWSER, + KICAD_MANAGER_FRAME::OnUpdatePreferredPdfBrowser ) + EVT_UPDATE_UI_RANGE( ID_TO_SCH, ID_TO_PCB_FP_EDITOR, + KICAD_MANAGER_FRAME::OnUpdateRequiresProject ) + +END_EVENT_TABLE() + +enum hotkey_id_commnand +{ + HK_RUN_EESCHEMA = HK_COMMON_END, + HK_LOAD_PROJECT, + HK_SAVE_PROJECT, + HK_NEW_PRJ, + HK_NEW_PRJ_TEMPLATE, + HK_RUN_LIBEDIT, + HK_RUN_PCBNEW, + HK_RUN_FPEDITOR, + HK_RUN_GERBVIEW, + HK_RUN_BM2COMPONENT, + HK_RUN_PCBCALCULATOR, + HK_RUN_PLEDITOR +}; + +///////////// Hotkeys management /////////////////////////////////////// + +// Remark: the hotkey message info is used as keyword in hotkey config files and +// as comments in help windows, therefore translated only when displayed +// they are marked _HKI to be extracted by translation tools +// See hotkeys_basic.h for more info + +// hotkeys command: +static EDA_HOTKEY HkHelp( _HKI( "Help (this window)" ), HK_HELP, '?' ); +static EDA_HOTKEY HkLoadPrj( _HKI( "Load project" ), HK_LOAD_PROJECT, 'O' + GR_KB_CTRL ); +static EDA_HOTKEY HkSavePrj( _HKI( "Save project" ), HK_SAVE_PROJECT, 'S' + GR_KB_CTRL ); +static EDA_HOTKEY HkNewProject( _HKI( "New Project" ), HK_NEW_PRJ, 'N' + GR_KB_CTRL ); +static EDA_HOTKEY HkNewPrjFromTemplate( _HKI( "New Prj From Template" ), + HK_NEW_PRJ_TEMPLATE, 'T' + GR_KB_CTRL ); + +static EDA_HOTKEY HkRunEeschema( _HKI( "Run Eeschema" ), HK_RUN_EESCHEMA, 'E' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunLibedit( _HKI( "Run LibEdit" ), HK_RUN_LIBEDIT, 'L' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunPcbnew( _HKI( "Run Pcbnew" ), HK_RUN_PCBNEW, 'P' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunModedit( _HKI( "Run FpEditor" ), HK_RUN_FPEDITOR, 'F' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunGerbview( _HKI( "Run Gerbview" ), HK_RUN_GERBVIEW, 'G' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunBm2Cmp( _HKI( "Run Bitmap2Component" ), + HK_RUN_BM2COMPONENT, 'B' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunPcbCalc( _HKI( "Run PcbCalculator" ), + HK_RUN_PCBCALCULATOR, 'C' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunPleditor( _HKI( "Run PlEditor" ), HK_RUN_PLEDITOR, 'Y' + GR_KB_CTRL, 0 ); + +// List of hotkey descriptors +EDA_HOTKEY* common_Hotkey_List[] = +{ + &HkHelp, + &HkLoadPrj, &HkSavePrj, &HkNewProject, &HkNewPrjFromTemplate, + &HkRunEeschema, &HkRunLibedit, + &HkRunPcbnew, &HkRunModedit, &HkRunGerbview, + &HkRunBm2Cmp, &HkRunPcbCalc, &HkRunPleditor, + NULL +}; + +// list of sections and corresponding hotkey list for Kicad +// (used to create an hotkey config file, and edit hotkeys ) +// here we have only one section. +static wxString sectionTitle( _HKI( "Kicad Manager Hotkeys" ) ); + +struct EDA_HOTKEY_CONFIG kicad_Manager_Hokeys_Descr[] = { + { &g_CommonSectionTag, common_Hotkey_List, §ionTitle }, + { NULL, NULL, NULL } +}; +///////////// End hotkeys management /////////////////////////////////////// + + +/** + * @brief (Re)Create the menubar + */ +void KICAD_MANAGER_FRAME::ReCreateMenuBar() +{ + wxString msg; + static wxMenu* openRecentMenu; // Open Recent submenu, + // static to remember this menu + + m_manager_Hokeys_Descr = kicad_Manager_Hokeys_Descr; + + // Create and try to get the current menubar + wxMenuBar* menuBar = GetMenuBar(); + + if( !menuBar ) + menuBar = new wxMenuBar(); + + // Delete all existing menus so they can be rebuilt. + // This allows language changes of the menu text on the fly. + menuBar->Freeze(); + + // Before deleting, remove the menus managed by m_fileHistory + // (the file history will be updated when adding/removing files in history) + if( openRecentMenu ) + Pgm().GetFileHistory().RemoveMenu( openRecentMenu ); + + // Delete all existing menus + while( menuBar->GetMenuCount() ) + delete menuBar->Remove( 0 ); + + // Recreate all menus: + + // Menu File: + wxMenu* fileMenu = new wxMenu; + + // Open + msg = AddHotkeyName( _( "&Open Project" ), kicad_Manager_Hokeys_Descr, HK_LOAD_PROJECT ); + AddMenuItem( fileMenu, ID_LOAD_PROJECT, msg, + _( "Open existing project" ), + KiBitmap( open_project_xpm ) ); + + // File history + openRecentMenu = new wxMenu(); + Pgm().GetFileHistory().UseMenu( openRecentMenu ); + Pgm().GetFileHistory().AddFilesToMenu( ); + AddMenuItem( fileMenu, openRecentMenu, + wxID_ANY, + _( "Open &Recent" ), + _( "Open recent schematic project" ), + KiBitmap( open_project_xpm ) ); + + // New project creation + wxMenu* newprjSubMenu = new wxMenu(); + + msg = AddHotkeyName( _( "&New Project" ), kicad_Manager_Hokeys_Descr, HK_NEW_PRJ ); + AddMenuItem( newprjSubMenu, ID_NEW_PROJECT, msg, + _( "Create new blank project" ), + KiBitmap( new_project_xpm ) ); + + msg = AddHotkeyName( _( "New Project from &Template" ), + kicad_Manager_Hokeys_Descr, HK_NEW_PRJ_TEMPLATE ); + AddMenuItem( newprjSubMenu, ID_NEW_PROJECT_FROM_TEMPLATE, msg, + _( "Create a new project from a template" ), + KiBitmap( new_project_with_template_xpm ) ); + + AddMenuItem( fileMenu, newprjSubMenu, + wxID_ANY, + _( "New Project" ), + _( "Create new project" ), + KiBitmap( new_project_xpm ) ); + + // Currently there is nothing to save + // (Kicad manager does not save any info in .pro file) +#if 0 + // Save + msg = AddHotkeyName( _( "&Save" ), kicad_Manager_Hokeys_Descr, HK_SAVE_PROJECT ); + AddMenuItem( fileMenu, ID_SAVE_PROJECT, msg, + _( "Save current project" ), + KiBitmap( save_project_xpm ) ); +#endif + + // Archive + fileMenu->AppendSeparator(); + AddMenuItem( fileMenu, + ID_SAVE_AND_ZIP_FILES, + _( "&Archive" ), + _( "Archive project files in zip archive" ), + KiBitmap( zip_xpm ) ); + + // Unarchive + AddMenuItem( fileMenu, + ID_READ_ZIP_ARCHIVE, + _( "&Unarchive" ), + _( "Unarchive project files from zip file" ), + KiBitmap( unzip_xpm ) ); + + // Separator + fileMenu->AppendSeparator(); + + // Quit + AddMenuItem( fileMenu, + wxID_EXIT, + _( "&Close" ), + _( "Close KiCad" ), + KiBitmap( exit_xpm ) ); + + // Menu Browse: + wxMenu* browseMenu = new wxMenu(); + + // Text editor + AddMenuItem( browseMenu, + ID_TO_TEXT_EDITOR, + _( "Open Text E&ditor" ), + _( "Launch preferred text editor" ), + KiBitmap( editor_xpm ) ); + + // View file + AddMenuItem( browseMenu, + ID_BROWSE_AN_SELECT_FILE, + _( "&Open Local File" ), + _( "Edit local file" ), + KiBitmap( browse_files_xpm ) ); + + // Menu Preferences: + wxMenu* preferencesMenu = new wxMenu; + + // Path configuration edit dialog. + AddMenuItem( preferencesMenu, + ID_PREFERENCES_CONFIGURE_PATHS, + _( "Configure Pa&ths" ), + _( "Edit path configuration environment variables" ), + KiBitmap( editor_xpm ) ); + + // Text editor + AddMenuItem( preferencesMenu, + ID_SELECT_PREFERED_EDITOR, + _( "&Set Text Editor" ), + _( "Set your preferred text editor" ), + KiBitmap( editor_xpm ) ); + + // PDF Viewer submenu:System browser or user defined checkbox + wxMenu* SubMenuPdfBrowserChoice = new wxMenu; + + // Default + AddMenuItem( SubMenuPdfBrowserChoice, ID_SELECT_DEFAULT_PDF_BROWSER, + _( "System &Default PDF Viewer" ), + _( "Use system default PDF viewer" ), + KiBitmap( datasheet_xpm ), + wxITEM_CHECK ); + SubMenuPdfBrowserChoice->Check( ID_SELECT_DEFAULT_PDF_BROWSER, + Pgm().UseSystemPdfBrowser() ); + + // Favourite + AddMenuItem( SubMenuPdfBrowserChoice, ID_SELECT_PREFERED_PDF_BROWSER, + _( "&Favourite PDF Viewer" ), + _( "Use favourite PDF viewer" ), + KiBitmap( datasheet_xpm ), + wxITEM_CHECK ); + SubMenuPdfBrowserChoice->Check( ID_SELECT_PREFERED_PDF_BROWSER, + !Pgm().UseSystemPdfBrowser() ); + + SubMenuPdfBrowserChoice->AppendSeparator(); + // Append PDF Viewer submenu to preferences + AddMenuItem( SubMenuPdfBrowserChoice, + ID_SELECT_PREFERED_PDF_BROWSER_NAME, + _( "Set &PDF Viewer" ), + _( "Set favourite PDF viewer" ), + KiBitmap( datasheet_xpm ) ); + + // PDF viewer submenu + AddMenuItem( preferencesMenu, SubMenuPdfBrowserChoice, -1, + _( "&PDF Viewer" ), + _( "PDF viewer preferences" ), + KiBitmap( datasheet_xpm ) ); + + // Hotkey submenu + preferencesMenu->AppendSeparator(); + AddHotkeyConfigMenu( preferencesMenu ); + + // Language submenu + preferencesMenu->AppendSeparator(); + Pgm().AddMenuLanguageList( preferencesMenu ); + + // Menu Tools: + wxMenu* toolsMenu = new wxMenu; + + msg = AddHotkeyName( _( "Run Eeschema" ), kicad_Manager_Hokeys_Descr, HK_RUN_EESCHEMA ); + AddMenuItem( toolsMenu, ID_TO_SCH, msg, KiBitmap( eeschema_xpm ) ); + + msg = AddHotkeyName( _( "Run Library Editor" ), + kicad_Manager_Hokeys_Descr, HK_RUN_LIBEDIT ); + AddMenuItem( toolsMenu, ID_TO_SCH_LIB_EDITOR, msg, KiBitmap( libedit_xpm ) ); + + msg = AddHotkeyName( _( "Run Pcbnew" ), + kicad_Manager_Hokeys_Descr, HK_RUN_PCBNEW ); + AddMenuItem( toolsMenu, ID_TO_PCB, msg, KiBitmap( pcbnew_xpm ) ); + + msg = AddHotkeyName( _( "Run Footprint Editor" ), + kicad_Manager_Hokeys_Descr, HK_RUN_FPEDITOR ); + AddMenuItem( toolsMenu, ID_TO_PCB_FP_EDITOR, msg, KiBitmap( module_editor_xpm ) ); + + msg = AddHotkeyName( _( "Run Gerbview" ), + kicad_Manager_Hokeys_Descr, HK_RUN_GERBVIEW ); + AddMenuItem( toolsMenu, ID_TO_GERBVIEW, msg, KiBitmap( icon_gerbview_small_xpm ) ); + + msg = AddHotkeyName( _( "Run Bitmap2Component" ), + kicad_Manager_Hokeys_Descr, HK_RUN_BM2COMPONENT ); + AddMenuItem( toolsMenu, ID_TO_BITMAP_CONVERTER, msg, + _( "Bitmap2Component - Convert bitmap images to Eeschema\n" + "or Pcbnew elements" ), + KiBitmap( image_xpm ) ); + + msg = AddHotkeyName( _( "Run Pcb Calculator" ), kicad_Manager_Hokeys_Descr, HK_RUN_PCBCALCULATOR ); + AddMenuItem( toolsMenu, ID_TO_PCB_CALCULATOR, msg, + _( "Pcb calculator - Calculator for components, track width, etc." ), + KiBitmap( options_module_xpm ) ); + + msg = AddHotkeyName( _( "Run Page Layout Editor" ), kicad_Manager_Hokeys_Descr, HK_RUN_PLEDITOR ); + AddMenuItem( toolsMenu, ID_TO_PL_EDITOR, msg, + _( "Pl editor - Worksheet layout editor" ), + KiBitmap( pagelayout_load_xpm ) ); + + // Menu Help: + wxMenu* helpMenu = new wxMenu; + + // Version info + AddHelpVersionInfoMenuEntry( helpMenu ); + + // Contents + AddMenuItem( helpMenu, wxID_HELP, + _( "KiCad &Manual" ), + _( "Open KiCad user manual" ), + KiBitmap( online_help_xpm ) ); + + AddMenuItem( helpMenu, wxID_INDEX, + _( "&Getting Started in KiCad" ), + _( "Open \"Getting Started in KiCad\" guide for beginners" ), + KiBitmap( help_xpm ) ); + + // Separator + helpMenu->AppendSeparator(); + + // About + AddMenuItem( helpMenu, wxID_ABOUT, + _( "&About KiCad" ), + _( "About KiCad" ), + KiBitmap( info_xpm ) ); + + // Create the menubar and append all submenus + menuBar->Append( fileMenu, _( "&File" ) ); + menuBar->Append( browseMenu, _( "&Browse" ) ); + menuBar->Append( preferencesMenu, _( "&Preferences" ) ); + menuBar->Append( toolsMenu, _( "&Tools" ) ); + menuBar->Append( helpMenu, _( "&Help" ) ); + + menuBar->Thaw(); + + // Associate the menu bar with the frame, if no previous menubar + if( GetMenuBar() == NULL ) + SetMenuBar( menuBar ); + else + menuBar->Refresh(); + + // Add the hotkey to the "show hotkey list" menu, because we do not have + // a management of the keyboard keys in Kicad. + // So all hotheys should be added to the menubar + // Note Use wxMenuBar::SetLabel only after the menubar + // has been associated with a frame. (see wxWidgets doc) + msg = AddHotkeyName( menuBar->GetLabel( ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST ), + kicad_Manager_Hokeys_Descr, HK_HELP ); + menuBar->SetLabel( ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST, msg ); +} + + +/** + * @brief (Re)Create the horizontal toolbar + */ +void KICAD_MANAGER_FRAME::RecreateBaseHToolbar() +{ + // Check if toolbar is not already created + if( m_mainToolBar != NULL ) + return; + + // Allocate memory for m_mainToolBar + m_mainToolBar = new wxAuiToolBar( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, + wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_HORZ_LAYOUT ); + + // New + m_mainToolBar->AddTool( ID_NEW_PROJECT, wxEmptyString, + KiBitmap( new_project_xpm ), + _( "Create new project" ) ); + + m_mainToolBar->AddTool( ID_NEW_PROJECT_FROM_TEMPLATE, wxEmptyString, + KiBitmap( new_project_with_template_xpm ), + _( "Create new project from template" ) ); + + // Load + m_mainToolBar->AddTool( ID_LOAD_PROJECT, wxEmptyString, + KiBitmap( open_project_xpm ), + _( "Open existing project" ) ); + + // Save + m_mainToolBar->AddTool( ID_SAVE_PROJECT, wxEmptyString, + KiBitmap( save_project_xpm ), + _( "Save current project" ) ); + + // Separator + m_mainToolBar->AddSeparator(); + + // Archive + m_mainToolBar->AddTool( ID_SAVE_AND_ZIP_FILES, wxEmptyString, + KiBitmap( zip_xpm ), + _( "Archive all project files" ) ); + + // Separator + m_mainToolBar->AddSeparator(); + + // Refresh project tree + m_mainToolBar->AddTool( ID_PROJECT_TREE_REFRESH, wxEmptyString, + KiBitmap( reload_xpm ), + _( "Refresh project tree" ) ); + + // Create m_mainToolBar + m_mainToolBar->Realize(); +} diff --git a/kicad/pgm_kicad.h b/kicad/pgm_kicad.h new file mode 100644 index 0000000..bb1069e --- /dev/null +++ b/kicad/pgm_kicad.h @@ -0,0 +1,76 @@ +#ifndef PGM_KICAD_H_ +#define PGM_KICAD_H_ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 2014 KiCad Developers, see CHANGELOG.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 + */ + + +#include <pgm_base.h> +#include <bin_mod.h> + + +/** + * Class PGM_KICAD + * extends PGM_BASE to bring in FileHistory() and PdfBrowser() which were moved + * from EDA_APP into KIFACE_I. KIFACE_I is not applicable in the project manager + * since it is not a KIFACE. This header is in the kicad directory since nobody + * else needs to know about it. + */ +class PGM_KICAD : public PGM_BASE +{ +public: + PGM_KICAD() : + m_bm( "kicad" ) // indicates a "$HOME/.kicad wxConfig like" config file. + {} + + ~PGM_KICAD() + { + destroy(); + } + + bool OnPgmInit( wxApp* aWxApp ); // overload PGM_BASE virtual + void OnPgmExit(); // overload PGM_BASE virtual + void MacOpenFile( const wxString& aFileName ); // overload PGM_BASE virtual + + wxFileHistory& GetFileHistory() { return m_bm.m_history; } + + wxConfigBase* PgmSettings() { return m_bm.m_config; } + + SEARCH_STACK& SysSearch() { return m_bm.m_search; } + + wxString GetHelpFileName() { return m_bm.m_help_file; } + +protected: + + // The PGM_* classes can have difficulties at termination if they + // are not destroyed soon enough. Relying on a static destructor can be + // too late for contained objects like wxSingleInstanceChecker. + void destroy(); + + BIN_MOD m_bm; +}; + + +extern PGM_KICAD& Pgm(); + +#endif // PGM_KICAD_H_ diff --git a/kicad/preferences.cpp b/kicad/preferences.cpp new file mode 100644 index 0000000..2f0e02c --- /dev/null +++ b/kicad/preferences.cpp @@ -0,0 +1,96 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2008-2014 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.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 preferences.cpp + */ + +#include <fctsys.h> +#include <pgm_kicad.h> +#include <confirm.h> +#include <gestfich.h> + +#include <kicad.h> + +#include <wx/fontdlg.h> + + +void KICAD_MANAGER_FRAME::OnUpdateDefaultPdfBrowser( wxUpdateUIEvent& event ) +{ + event.Check( Pgm().UseSystemPdfBrowser() ); +} + + +void KICAD_MANAGER_FRAME::OnSelectDefaultPdfBrowser( wxCommandEvent& event ) +{ + Pgm().ForceSystemPdfBrowser( true ); + Pgm().WritePdfBrowserInfos(); +} + + +void KICAD_MANAGER_FRAME::OnUpdatePreferredPdfBrowser( wxUpdateUIEvent& event ) +{ + event.Check( !Pgm().UseSystemPdfBrowser() ); +} + + +void KICAD_MANAGER_FRAME::OnSelectPreferredPdfBrowser( wxCommandEvent& event ) +{ + bool setPdfBrowserName = event.GetId() == ID_SELECT_PREFERED_PDF_BROWSER_NAME; + + if( !Pgm().GetPdfBrowserName() && !setPdfBrowserName ) + { + DisplayError( this, + _( "You must choose a PDF viewer before using this option." ) ); + setPdfBrowserName = true; + } + + if( setPdfBrowserName ) + { + wxString mask( wxT( "*" ) ); + + #ifdef __WINDOWS__ + mask += wxT( ".exe" ); + #endif + + wxString wildcard = _( "Executable files (" ) + mask + wxT( ")|" ) + mask; + + Pgm().ReadPdfBrowserInfos(); + wxFileName fn = Pgm().GetPdfBrowserName(); + + wxFileDialog dlg( this, _( "Select Preferred PDF Browser" ), fn.GetPath(), + fn.GetFullPath(), wildcard, + wxFD_OPEN | wxFD_FILE_MUST_EXIST ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + Pgm().SetPdfBrowserName( dlg.GetPath() ); + } + + Pgm().ForceSystemPdfBrowser( false ); + Pgm().WritePdfBrowserInfos(); +} + diff --git a/kicad/prjconfig.cpp b/kicad/prjconfig.cpp new file mode 100644 index 0000000..c8ed495 --- /dev/null +++ b/kicad/prjconfig.cpp @@ -0,0 +1,398 @@ +/** + * @file prjconfig.cpp + * Load and save project configuration files (*.pro) + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2015 Jean-Pierre Charras + * 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 + */ + +#include <fctsys.h> +#include <pgm_kicad.h> +#include <kiway.h> +#include <project.h> +#include <confirm.h> +#include <gestfich.h> +#include <kicad.h> +#include <config_params.h> +#include <project_template.h> +#include <tree_project_frame.h> +#include <wildcards_and_files_ext.h> +#include <vector> +#include <build_version.h> +#include <macros.h> +#include <common.h> + +#include <wx/dir.h> +#include <wx/filename.h> +#include <wx/stdpaths.h> + +#include "dialogs/dialog_template_selector.h" + +#define SEP() wxFileName::GetPathSeparator() + +// Not really useful, provided to save/restore params in project config file, +// (Add them in s_KicadManagerParams if any) +// Used also to create new .pro files from the kicad.pro template file +// for new projects +#define GeneralGroupName wxT( "/general" ) + +PARAM_CFG_ARRAY s_KicadManagerParams; + +void KICAD_MANAGER_FRAME::CreateNewProject( const wxString& aPrjFullFileName, + bool aTemplateSelector = false ) +{ + wxFileName newProjectName = aPrjFullFileName; + wxChar sep[2] = { SEP(), 0 }; // nul terminated separator wxChar string. + + ClearMsg(); + + // If we are creating a project from a template, make sure the template directory is sane + if( aTemplateSelector ) + { + DIALOG_TEMPLATE_SELECTOR* ps = new DIALOG_TEMPLATE_SELECTOR( this ); + + wxFileName templatePath; + wxString envStr; + +#ifndef __WXMAC__ + wxGetEnv( wxT( "KICAD" ), &envStr ); + + // Add a new tab for system templates + if( !envStr.empty() ) + { + // user may or may not have including terminating separator. + if( !envStr.EndsWith( sep ) ) + envStr += sep; + + templatePath = envStr + wxT( "template" ) + sep; + } + else + { + // The standard path should be in the share directory for kicad. As + // it is normal on Windows to only have the share directory and not + // the kicad sub-directory we fall back to that if the directory + // doesn't exist + templatePath = wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) + + sep + wxT( ".." ) + sep + wxT( "share" ) + sep + wxT( "kicad" ) + + sep + wxT( "template" ) + sep; + + if( !wxDirExists( templatePath.GetFullPath() ) ) + { + templatePath = wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) + + sep + wxT( ".." ) + sep + wxT( "share" ) + sep + wxT( "template" ) + sep; + } + } +#else + // Use what is provided in the bundle data dir + templatePath = GetOSXKicadDataDir() + sep + wxT( "template" ); +#endif + + ps->AddTemplatesPage( _( "System Templates" ), templatePath ); + + // Add a new tab for user templates + wxFileName userPath = wxStandardPaths::Get().GetDocumentsDir() + + sep + wxT( "kicad" ) + sep + wxT( "template" ) + sep; + + ps->AddTemplatesPage( _( "User Templates" ), userPath ); + + // Check to see if a custom template location is available and setup a + // new selection tab if there is. + envStr.clear(); + wxGetEnv( wxT( "KICAD_PTEMPLATES" ), &envStr ); + + if( !envStr.empty() ) + { + if( !envStr.EndsWith( sep ) ) + envStr += sep; + + wxFileName envPath = envStr; + + ps->AddTemplatesPage( _( "Portable Templates" ), envPath ); + } + + // Show the project template selector dialog + int result = ps->ShowModal(); + + if( ( result != wxID_OK ) || ( ps->GetSelectedTemplate() == NULL ) ) + { + if( ps->GetSelectedTemplate() == NULL ) + { + wxMessageBox( _( "No project template was selected. Cannot generate new " + "project." ), + _( "Error" ), + wxOK | wxICON_ERROR, + this ); + } + } + else + { + // The selected template widget contains the template we're attempting to use to + // create a project + if( !ps->GetSelectedTemplate()->CreateProject( newProjectName ) ) + { + wxMessageBox( _( "Problem whilst creating new project from template!" ), + _( "Template Error" ), + wxOK | wxICON_ERROR, + this ); + } + } + } + + // Init project filename + SetProjectFileName( newProjectName.GetFullPath() ); + + // Write settings to project file + // was: wxGetApp().WriteProjectConfig( aPrjFullFileName, GeneralGroupName, s_KicadManagerParams ); + Prj().ConfigSave( Pgm().SysSearch(), GeneralGroupName, s_KicadManagerParams ); + + // Ensure a "stub" for a schematic root sheet and a board exist. + // It will avoid messages from the schematic editor or the board editor to create a new file + // And forces the user to create main files under the right name for the project manager + wxFileName fn( newProjectName.GetFullPath() ); + fn.SetExt( SchematicFileExtension ); + + // If a <project>.sch file does not exist, create a "stub" file + if( !fn.FileExists() ) + { + wxFile file( fn.GetFullPath(), wxFile::write ); + + if( file.IsOpened() ) + file.Write( wxT( "EESchema Schematic File Version 2\n" ) ); + + // wxFile dtor will close the file + } + + // If a <project>.kicad_pcb or <project>.brd file does not exist, + // create a .kicad_pcb "stub" file + fn.SetExt( KiCadPcbFileExtension ); + wxFileName leg_fn( fn ); + leg_fn.SetExt( LegacyPcbFileExtension ); + + if( !fn.FileExists() && !leg_fn.FileExists() ) + { + wxFile file( fn.GetFullPath(), wxFile::write ); + + if( file.IsOpened() ) + file.Write( wxT( "(kicad_pcb (version 4) (host kicad \"dummy file\") )\n" ) ); + + // wxFile dtor will close the file + } + + // Enable the toolbar and menubar buttons and clear the help text. + m_active_project = true; + m_MessagesBox->Clear(); +} + + +void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event ) +{ + // Any open KIFACE's must be closed if they are not part of the new project. + // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.) + // User is prompted here to close those KIWAY_PLAYERs: + if( !Kiway.PlayersClose( false ) ) + return; + + // evt_id can be one of: + // ID_NEW_PROJECT, ID_NEW_PROJECT_FROM_TEMPLATE, ID_LOAD_PROJECT, and + // wxID_ANY from 3 different places. + int evt_id = event.GetId(); + + wxString title; + + ClearMsg(); + + bool newProject = ( evt_id == ID_NEW_PROJECT ) || + ( evt_id == ID_NEW_PROJECT_FROM_TEMPLATE ); + + if( evt_id != wxID_ANY ) + { + int style; + + if( newProject ) + { + title = _( "Create New Project" ); + style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT; + } + else + { + title = _( "Open Existing Project" ); + style = wxFD_OPEN | wxFD_FILE_MUST_EXIST; + } + + wxString default_dir = GetMruPath(); + wxFileDialog dlg( this, title, default_dir, wxEmptyString, + ProjectFileWildcard, style ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + //DBG( printf( "%s: wxFileDialog::GetPath=%s\n", __func__, TO_UTF8( dlg.GetPath() ) );) + + wxFileName pro( dlg.GetPath() ); + pro.SetExt( ProjectFileExtension ); // enforce extension + + if( !pro.IsAbsolute() ) + pro.MakeAbsolute(); + + if( newProject ) + { + // Check if the project directory is empty + wxDir directory( pro.GetPath() ); + + if( directory.HasFiles() ) + { + wxString msg = _( "The selected directory is not empty. We recommend you " + "create projects in their own clean directory.\n\nDo you " + "want to create a new empty directory for the project?" ); + + if( IsOK( this, msg ) ) + { + // Append a new directory with the same name of the project file + // and try to create it + pro.AppendDir( pro.GetName() ); + + if( !wxMkdir( pro.GetPath() ) ) + // There was a problem, undo + pro.RemoveLastDir(); + } + } + + if( evt_id == ID_NEW_PROJECT ) + { + CreateNewProject( pro.GetFullPath() ); + } + else if( evt_id == ID_NEW_PROJECT_FROM_TEMPLATE ) + { + // Launch the template selector dialog + CreateNewProject( pro.GetFullPath(), true ); + } + } + + SetProjectFileName( pro.GetFullPath() ); + } + + wxString prj_filename = GetProjectFileName(); + + wxString nameless_prj = NAMELESS_PROJECT wxT( ".pro" ); + + wxLogDebug( wxT( "%s: %s" ), + GetChars( wxFileName( prj_filename ).GetFullName() ), + GetChars( nameless_prj ) ); + + // Check if project file exists and if it is not noname.pro + if( !wxFileExists( prj_filename ) + && !wxFileName( prj_filename ).GetFullName().IsSameAs( nameless_prj ) ) + { + wxString msg = wxString::Format( _( + "KiCad project file '%s' not found" ), + GetChars( prj_filename ) ); + + DisplayError( this, msg ); + return; + } + + // Either this is the first time kicad has been run or one of the projects in the + // history list is no longer valid. This prevents kicad from automatically creating + // a noname.pro file in the same folder as the kicad binary. + if( wxFileName( prj_filename ).GetFullName().IsSameAs( nameless_prj ) && !newProject ) + { + m_active_project = false; + m_MessagesBox->SetValue( _( "To proceed, you can use the File menu to start a new project." ) ); + return; + } + else + { + m_active_project = true; + m_MessagesBox->Clear(); + } + + Prj().ConfigLoad( Pgm().SysSearch(), GeneralGroupName, s_KicadManagerParams ); + + title = wxT( "KiCad " ) + GetBuildVersion() + wxT( ' ' ) + prj_filename; + + if( !wxFileName( prj_filename ).IsDirWritable() ) + title += _( " [Read Only]" ); + else + SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access. + + SetTitle( title ); + + if( !prj_filename.IsSameAs( nameless_prj ) ) + UpdateFileHistory( prj_filename, &Pgm().GetFileHistory() ); + + m_LeftWin->ReCreateTreePrj(); + + // Rebuild the list of watched paths. + // however this is possible only when the main loop event handler is running, + // so we use it to run the rebuild function. + wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS ); + + wxPostEvent( this, cmd ); + + PrintPrjInfo(); +} + + +/* Creates a new project folder, copy a template into this new folder. + * and open this new project as working project + */ +void KICAD_MANAGER_FRAME::OnCreateProjectFromTemplate( wxCommandEvent& event ) +{ + wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep(); + wxString title = _("New Project Folder"); + wxDirDialog dlg( this, title, default_dir ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + // Builds the project .pro filename, from the new project folder name + wxFileName fn; + fn.AssignDir( dlg.GetPath() ); + fn.SetName( dlg.GetPath().AfterLast( SEP() ) ); + fn.SetExt( wxT( "pro" ) ); + + // Launch the template selector dialog, and copy files + CreateNewProject( fn.GetFullPath(), true ); + + // Initialize the project + event.SetId( wxID_ANY ); + OnLoadProject( event ); +} + + +void KICAD_MANAGER_FRAME::OnSaveProject( wxCommandEvent& event ) +{ + if( !wxIsWritable( GetProjectFileName() ) ) + return; + + // was: wxGetApp().WriteProjectConfig( m_ProjectFileName.GetFullPath(), + // GeneralGroupName, s_KicadManagerParams ); + Prj().ConfigSave( Pgm().SysSearch(), GeneralGroupName, s_KicadManagerParams ); +} + + +void KICAD_MANAGER_FRAME::OnUpdateRequiresProject( wxUpdateUIEvent& event ) +{ + event.Enable( m_active_project ); +} diff --git a/kicad/project_template.cpp b/kicad/project_template.cpp new file mode 100644 index 0000000..b4f088c --- /dev/null +++ b/kicad/project_template.cpp @@ -0,0 +1,236 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Brian Sidebotham <brian.sidebotham@gmail.com> + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 + */ + +#include "project_template.h" + +#include <vector> + +#include <wx/wx.h> +#include <wx/arrstr.h> +#include <wx/dir.h> +#include <wx/filename.h> +#include <wx/txtstrm.h> +#include <wx/wfstream.h> + +#include <macros.h> + + +#define SEP() wxFileName::GetPathSeparator() + + +PROJECT_TEMPLATE::PROJECT_TEMPLATE( const wxString& aPath ) +{ + templateBasePath = wxFileName::DirName( aPath ); + templateMetaPath = wxFileName::DirName( aPath + SEP() + METADIR ); + templateMetaHtmlFile = wxFileName::FileName( aPath + SEP() + METADIR + SEP() + + METAFILE_INFO_HTML ); + templateMetaIconFile = wxFileName::FileName( aPath + SEP() + METADIR + SEP() + METAFILE_ICON ); + + title = wxEmptyString; + + // Test the project template requirements to make sure aPath is a valid + // template structure + if( !wxFileName::DirExists( templateBasePath.GetPath() ) ) + { + // Error, the path doesn't exist! + title = wxT( "Could open the template path! " + aPath ); + } + else if( !wxFileName::DirExists( templateMetaPath.GetPath() ) ) + { + // Error, the meta information directory doesn't exist! + title = wxT( "Couldn't open the meta information directory for this template! " + + templateMetaPath.GetPath() ); + } + else if( !wxFileName::FileExists( templateMetaHtmlFile.GetFullPath() ) ) + { + // Error, the meta information directory doesn't contain the informational html file! + title = wxT( "Cound't find the meta html information file for this template!" ); + } + + // Try to load an icon + metaIcon = new wxBitmap( templateMetaIconFile.GetFullPath(), wxBITMAP_TYPE_PNG ); +} + +std::vector<wxFileName> PROJECT_TEMPLATE::GetFileList() +{ + std::vector<wxFileName> files; + wxString f = templateBasePath.GetPath(); + wxArrayString allfiles; + wxFileName p; + + wxDir::GetAllFiles( f, &allfiles ); + + // Create the vector and ignore all of the meta data files! + for( size_t i=0; i < allfiles.size(); i++ ) + { + p = allfiles[i]; + + // Files that are in the meta directory must not be included + if( !p.GetPath().StartsWith( templateMetaPath.GetPath() ) ) + files.push_back(allfiles[i]); + } + + return files; +} + + +wxString PROJECT_TEMPLATE::GetPrjDirName() +{ + return templateBasePath.GetDirs()[ templateBasePath.GetDirCount()-1 ]; +} + + +PROJECT_TEMPLATE::~PROJECT_TEMPLATE() +{ + +} + + +wxFileName PROJECT_TEMPLATE::GetHtmlFile() +{ + return templateMetaHtmlFile; +} + + +wxBitmap* PROJECT_TEMPLATE::GetIcon() +{ + return metaIcon; +} + + +bool PROJECT_TEMPLATE::CreateProject( wxFileName& aNewProjectPath ) +{ + // CreateProject copy the files from template to the new project folder + // and rename files which have the same name as the template .pro file + bool result = true; + + std::vector<wxFileName> srcFiles = GetFileList(); + + // Find the template file name base. this is the name of the .pro templte file + wxString basename; + for( size_t i=0; i < srcFiles.size(); i++ ) + { + if( srcFiles[i].GetExt() == wxT( "pro" ) ) + { + basename = srcFiles[i].GetName(); + break; + } + } + + for( size_t i=0; i < srcFiles.size(); i++ ) + { + // Replace the template path + wxFileName destination = srcFiles[i]; + + // Replace the template filename with the project filename for the new project creation + wxString currname = destination.GetName(); + currname.Replace( basename, aNewProjectPath.GetName() ); + destination.SetName( currname ); + + // Replace the template path with the project path for the new project creation + // but keep the sub directory name, if exists + wxString destpath = destination.GetPathWithSep(); + destpath.Replace( templateBasePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() ); + + // Check to see if the path already exists, if not attempt to create it here. Don't worry + // about error checking, if the path isn't created the file copy will fail anyway + + if( !wxFileName::DirExists( destpath ) ) + wxFileName::Mkdir( destpath, 0777, wxPATH_MKDIR_FULL ); + + destination.SetPath( destpath ); + + wxString srcFile = srcFiles[i].GetFullPath(); + wxString dstFile = destination.GetFullPath(); + + if( !wxCopyFile( srcFile, dstFile ) ) + { + result = false; + break; + } + } + + return result; +} + + +wxString* PROJECT_TEMPLATE::GetTitle(void) +{ + wxFileInputStream input( GetHtmlFile().GetFullPath() ); + wxString separator( wxT( "\x9" ) ); + wxTextInputStream text( input, separator, wxConvUTF8 ); + + /* Open HTML file and get the text between the title tags */ + if( title == wxEmptyString ) + { + int start = 0; + int finish = 0; + bool done = false; + + while( input.IsOk() && !input.Eof() && !done ) + { + wxString line = text.ReadLine(); + + start = line.Find( wxT( "<title>" ) ); + if( start == wxNOT_FOUND ) + start = line.Find( wxT( "<TITLE>" ) ); + + finish = line.Find( wxT( "</title>" ) ); + if( finish == wxNOT_FOUND ) + finish = line.Find( wxT( "</TITLE>" ) ); + + // find the opening tag + if( start != wxNOT_FOUND ) + { + if( finish != wxNOT_FOUND ) + { + title = line.SubString( start + 7, finish ); + } + else + { + title = line.SubString( start + 7, line.Len() - 1 ); + done = true; + } + } + else + { + if( finish != wxNOT_FOUND ) + { + title += line.SubString( 0, finish ); + done = true; + } + else + { + title += line; + } + } + + // Remove line endings + title.Replace( wxT( "\r" ), wxT( "" ) ); + title.Replace( wxT( "\n" ), wxT( "" ) ); + } + } + + return &title; +} diff --git a/kicad/project_template.h b/kicad/project_template.h new file mode 100644 index 0000000..aaef83e --- /dev/null +++ b/kicad/project_template.h @@ -0,0 +1,204 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Brian Sidebotham <brian.sidebotham@gmail.com> + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 + */ + +/** + @page prj_tmp Project Templates + + Author: Brian Sidebotham + + Proposal + -------- + + To add new project template functionality to KiCad to facilitate the easy setup of projects + which have common attributes such as pre-defined board outlines, connector positions, + schematic elements, design rules, etc. + + + Definitions + ----------- + + A template is a directory of files, which includes a directory of metadata. The template system + name (SYSNAME) is the directory name under which the template files are stored. The metadata + directory (METADIR) contains pre-defined files which provide information about the template. + + All files and directories in a template are copied to the new project path when a project is + created using a template, except METADIR. + + All files and directories which start with SYSNAME will have SYSNAME replaced by the new + project file name, excluding the file extension. + + + Metadata + -------- + + A template's METADIR must contain the required files, and might optionally contain any of the + optional files + + Required Files + ~~~~~~~~~~~~~~ + + /info.html - Contains html formatted information about the template which is used by the + user to determine if the template is what they are after. The <title> tag + determines the actual name of the template that is exposed to the user for + template selection. Using html to format this document means that images can + be in-lined without having to invent a new scheme. Only HTML supported by + wxHTML can be used to format this document. + + Optional Files + ~~~~~~~~~~~~~~ + + /icon.png - A 64 x 64px PNG icon file which is used as a clickable icon in the template + selection dialog. + + + Operation + --------- + + The KiCad File menu will be modified to change New from a menu item to a pop-out menu item, in + the same manor as Open Recent. There will be two options on the pop-out menu: + + Blank -> Will act exactly the same as the current new menu item so that anyone who wishes to + create a blank project won't have their settings lost or feel alienated. + + From Template -> Will open the template selection dialog. + + The template selection dialog will have a list of icons on the left, and a wxHTML window to the + right. A single click on a template's icon on the left will load that templates info.html + metadata file and display it in the wxHTML window. + + A double click on a template's icon will start the new project creation and will open a new + file dialog. If the user selects a valid location for the new project, the template will be + copied to the new project location ( excluding METADIR as mentioned earlier ) and any files + that match the string replacement rules will be renamed to reflect the new project's name. + + The list of available templates will be gathered from the following sources: + + wxStandardPaths::GetExecutableDir()/../share/template/ + wxStandardPaths::GetUserDataDir()/templates/ + wxGetEnv(wxT("KICAD_PTEMPLATES")) + wxGetEnv(wxT("KICAD"))/template/ + +*/ + +#ifndef PROJECT_TEMPLATE_H +#define PROJECT_TEMPLATE_H + +#include <vector> + +#include <wx/wx.h> +#include <wx/image.h> +#include <wx/filename.h> + +/** + * @brief A directory which contains information about the project template and does not get + * copied. This define is the default filename for this directory + * + */ +#define METADIR wxT("meta") + + +/** + * @brief A required html formatted file which contains information about the project template. + * This define is the default filename for this file + * + */ +#define METAFILE_INFO_HTML wxT("info.html") + + +/** + * @brief An optional png icon, exactly 64px x 64px which is used in the template selector if + * present. This define is the default filename for this file + * + */ +#define METAFILE_ICON wxT("icon.png") + +/** + * @brief A class which provides project template functionality. + * + * + * + */ +class PROJECT_TEMPLATE { +private: +protected: + wxFileName templateBasePath; + wxFileName templateMetaPath; + wxFileName templateMetaHtmlFile; + wxFileName templateMetaIconFile; + wxBitmap* metaIcon; + wxString title; + +public: + + /** + * @brief Create a new project instance from \a aPath. \a aPath should be a directory that + * conforms to the project template requirements + * + * @param aPath Should be a directory containing the template + */ + PROJECT_TEMPLATE( const wxString& aPath ); + + /** + * @brief Non-virtual destructor (so no dervied classes) + */ + ~PROJECT_TEMPLATE(); + + /** + * @brief Get the dir name of the project template + * (i.e. the name of the last folder containing the template files) + * @return the dir name of the template + */ + wxString GetPrjDirName(); + + /** + * @brief Get the full Html filename for the project template + * @return the html meta information file for this template + */ + wxFileName GetHtmlFile(); + + /** + * @brief Copies and renames all template files to create a new project. + * @param aNewProjectPath The full path of the new project file to create + */ + bool CreateProject( wxFileName& aNewProjectPath ); + + /** + * @brief Get the 64px^2 icon for the project template + * @return an image file of 64px x 64px which is the templates icon + */ + wxBitmap* GetIcon(); + + /** + * @brief Get the title of the project (extracted from the html title tag) + */ + wxString* GetTitle(); + + /** + * @brief Get a vector list of filenames for the template. The files are the source files, + * and have not yet been through any renaming + */ + std::vector<wxFileName> GetFileList(); +}; + +#endif diff --git a/kicad/tree_project_frame.cpp b/kicad/tree_project_frame.cpp new file mode 100644 index 0000000..88df16a --- /dev/null +++ b/kicad/tree_project_frame.cpp @@ -0,0 +1,1093 @@ +/** + * @file tree_project_frame.cpp + * @brief Function to build the tree of files in the current project directory + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2016 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 + */ + +#include <fctsys.h> +#include <confirm.h> +#include <gestfich.h> +#include <pgm_base.h> +#include <macros.h> + +#include <tree_project_frame.h> +#include <class_treeprojectfiles.h> +#include <class_treeproject_item.h> +#include <wildcards_and_files_ext.h> + +#include <wx/regex.h> +#include <wx/dir.h> +#include <wx/imaglist.h> +#include <wx/stdpaths.h> +#include <menus_helpers.h> +#include <stack> + + +/* Note about the tree project build process: + * Building the tree project can be *very* long if there are a lot of subdirectories + * in the working directory. + * Unfortunately, this happens easily if the project file *.pro is in the home directory + * So the tree project is built "on demand": + * First the tree is built from the current directory and shows files and subdirs. + * > First level subdirs trees are built (i.e subdirs contents are not read) + * > When expanding a subdir, each subdir contains is read, + * and the corresponding sub tree is populated on the fly. + */ + +// list of files extensions listed in the tree project window +// *.sch files are always allowed, do not add here +// Add extensions in a compatible regex format to see others files types +static const wxChar* s_allowedExtensionsToList[] = +{ + wxT( "^.*\\.pro$" ), + wxT( "^.*\\.pdf$" ), + wxT( "^[^$].*\\.brd$" ), // Legacy Pcbnew files + wxT( "^[^$].*\\.kicad_pcb$" ), // S format Pcbnew board files + wxT( "^[^$].*\\.kicad_wks$" ), // S format kicad page layout descr files + wxT( "^[^$].*\\.kicad_mod$" ), // S format kicad footprint files, currently not listed + wxT( "^.*\\.net$" ), + wxT( "^.*\\.lib$" ), // Schematic library file + wxT( "^.*\\.txt$" ), + wxT( "^.*\\.pho$" ), // Gerber file (Old Kicad extension) + wxT( "^.*\\.gbr$" ), // Gerber file + wxT( "^.*\\.gb[alops]$" ), // Gerber back (or bottom) layer file + wxT( "^.*\\.gt[alops]$" ), // Gerber front (or top) layer file + wxT( "^.*\\.g[0-9]{1,2}$" ), // Gerber inner layer file + wxT( "^.*\\.odt$" ), + wxT( "^.*\\.htm$" ), + wxT( "^.*\\.html$" ), + wxT( "^.*\\.rpt$" ), // Report files + wxT( "^.*\\.csv$" ), // Report files in comma separated format + wxT( "^.*\\.pos$" ), // Footprint position files + wxT( "^.*\\.cmp$" ), // Cvpcb cmp/footprint link files + wxT( "^.*\\.drl$" ), // Excellon drill files + wxT( "^.*\\.svg$" ), // SVG print/plot files + NULL // end of list +}; + + +/* TODO: Check if these file extension and wildcard definitions are used + * in any of the other KiCad programs and move them into the common + * library as required. + */ + +// File extension definitions. +const wxChar TextFileExtension[] = wxT( "txt" ); + +// File wildcard definitions. +const wxChar TextFileWildcard[] = wxT( "Text files (*.txt)|*.txt" ); + + +/** + * @brief class TREE_PROJECT_FRAME is the frame that shows the tree list + * of files and subdirs inside the working directory + * Files are filtered (see s_allowedExtensionsToList) so + * only useful files are shown. + */ + + +BEGIN_EVENT_TABLE( TREE_PROJECT_FRAME, wxSashLayoutWindow ) + EVT_TREE_ITEM_ACTIVATED( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnSelect ) + EVT_TREE_ITEM_EXPANDED( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnExpand ) + EVT_TREE_ITEM_RIGHT_CLICK( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnRight ) + EVT_MENU( ID_PROJECT_TXTEDIT, TREE_PROJECT_FRAME::OnOpenSelectedFileWithTextEditor ) + EVT_MENU( ID_PROJECT_NEWDIR, TREE_PROJECT_FRAME::OnCreateNewDirectory ) + EVT_MENU( ID_PROJECT_DELETE, TREE_PROJECT_FRAME::OnDeleteFile ) + EVT_MENU( ID_PROJECT_RENAME, TREE_PROJECT_FRAME::OnRenameFile ) +END_EVENT_TABLE() + + +TREE_PROJECT_FRAME::TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ) : + wxSashLayoutWindow( parent, + ID_LEFT_FRAME, + wxDefaultPosition, + wxDefaultSize, + wxNO_BORDER | wxSW_3D | wxTAB_TRAVERSAL ) +{ + m_Parent = parent; + m_TreeProject = NULL; + + m_watcher = NULL; + Connect( wxEVT_FSWATCHER, + wxFileSystemWatcherEventHandler( TREE_PROJECT_FRAME::OnFileSystemEvent ) ); + + /* + * Filtering is now inverted: the filters are actually used to _enable_ support + * for a given file type. + */ + + // NOTE: sch filter must be first because of a test in AddFile() below + m_filters.push_back( wxT( "^.*\\.sch$" ) ); + + for( int ii = 0; s_allowedExtensionsToList[ii] != NULL; ii++ ) + m_filters.push_back( s_allowedExtensionsToList[ii] ); + + m_filters.push_back( wxT( "^no KiCad files found" ) ); + + ReCreateTreePrj(); +} + + +TREE_PROJECT_FRAME::~TREE_PROJECT_FRAME() +{ + if( m_watcher ) + { + m_watcher->RemoveAll(); + m_watcher->SetOwner( NULL ); + delete m_watcher; + } +} + + +void TREE_PROJECT_FRAME::RemoveFilter( const wxString& filter ) +{ + for( unsigned int i = 0; i < m_filters.size(); i++ ) + { + if( filter == m_filters[i] ) + { + m_filters.erase( m_filters.begin() + i ); + return; + } + } +} + + +void TREE_PROJECT_FRAME::OnCreateNewDirectory( wxCommandEvent& event ) +{ + // Get the root directory name: + TREEPROJECT_ITEM* treeData = GetSelectedData(); + + if( !treeData ) + return; + + TreeFileType rootType = treeData->GetType(); + wxTreeItemId root; + + if( TREE_DIRECTORY == rootType ) + { + root = m_TreeProject->GetSelection(); + } + else + { + root = m_TreeProject->GetItemParent( m_TreeProject->GetSelection() ); + + if( !root.IsOk() ) + root = m_TreeProject->GetSelection(); + } + + wxString prj_dir = wxPathOnly( m_Parent->GetProjectFileName() ); + + // Ask for the new sub directory name + wxString curr_dir = treeData->GetDir(); + + if( !curr_dir.IsEmpty() ) // A subdir is selected + { + // Make this subdir name relative to the current path. + // It will be more easy to read by the user, in the next dialog + wxFileName fn; + fn.AssignDir( curr_dir ); + fn.MakeRelativeTo( prj_dir ); + curr_dir = fn.GetPath(); + + if( !curr_dir.IsEmpty() ) + curr_dir += wxFileName::GetPathSeparator(); + } + + wxString msg = wxString::Format( _( "Current project directory:\n%s" ), GetChars( prj_dir ) ); + wxString subdir = wxGetTextFromUser( msg, _( "Create New Directory" ), curr_dir ); + + if( subdir.IsEmpty() ) + return; + + wxString full_dirname = prj_dir + wxFileName::GetPathSeparator() + subdir; + + if( wxMkdir( full_dirname ) ) + { + // the new itel will be added by the file watcher + // AddItemToTreeProject( subdir, root ); + } +} + + +wxString TREE_PROJECT_FRAME::GetFileExt( TreeFileType type ) +{ + wxString ext; + + switch( type ) + { + case TREE_PROJECT: + ext = ProjectFileExtension; + break; + + case TREE_SCHEMA: + ext = SchematicFileExtension; + break; + + case TREE_LEGACY_PCB: + ext = LegacyPcbFileExtension; + break; + + case TREE_SEXP_PCB: + ext = KiCadPcbFileExtension; + break; + + case TREE_GERBER: + ext = GerberFileExtension; + break; + + case TREE_HTML: + ext = HtmlFileExtension; + break; + + case TREE_PDF: + ext = PdfFileExtension; + break; + + case TREE_TXT: + ext = TextFileExtension; + break; + + case TREE_NET: + ext = NetlistFileExtension; + break; + + case TREE_CMP_LINK: + ext = ComponentFileExtension; + break; + + case TREE_REPORT: + ext = ReportFileExtension; + break; + + case TREE_FP_PLACE: + ext = FootprintPlaceFileExtension; + break; + + case TREE_DRILL: + ext = DrillFileExtension; + break; + + case TREE_SVG: + ext = SVGFileExtension; + break; + + case TREE_PAGE_LAYOUT_DESCR: + ext = PageLayoutDescrFileExtension; + break; + + case TREE_FOOTPRINT_FILE: + ext = KiCadFootprintFileExtension; + break; + + case TREE_SCHEMATIC_LIBFILE: + ext = SchematicLibraryFileExtension; + break; + + default: // Eliminates unnecessary GCC warning. + break; + } + + return ext; +} + + +/* + * Return the wxFileDialog wildcard string for the selected file type. + */ +wxString TREE_PROJECT_FRAME::GetFileWildcard( TreeFileType type ) +{ + wxString ext; + + switch( type ) + { + case TREE_PROJECT: + ext = ProjectFileWildcard; + break; + + case TREE_SCHEMA: + ext = SchematicFileWildcard; + break; + + case TREE_LEGACY_PCB: + case TREE_SEXP_PCB: + ext = PcbFileWildcard; + break; + + case TREE_GERBER: + ext = GerberFileWildcard; + break; + + case TREE_HTML: + ext = HtmlFileWildcard; + break; + + case TREE_PDF: + ext = PdfFileWildcard; + break; + + case TREE_TXT: + ext = TextFileWildcard; + break; + + case TREE_NET: + ext = NetlistFileWildcard; + break; + + case TREE_CMP_LINK: + ext = ComponentFileWildcard; + break; + + case TREE_REPORT: + ext = ReportFileWildcard; + break; + + case TREE_FP_PLACE: + ext = FootprintPlaceFileWildcard; + break; + + case TREE_DRILL: + ext = DrillFileWildcard; + break; + + case TREE_SVG: + ext = SVGFileWildcard; + break; + + case TREE_PAGE_LAYOUT_DESCR: + ext = PageLayoutDescrFileWildcard; + break; + + case TREE_FOOTPRINT_FILE: + ext = KiCadFootprintLibFileWildcard; + break; + + case TREE_SCHEMATIC_LIBFILE: + ext = SchematicLibraryFileWildcard; + break; + + default: // Eliminates unnecessary GCC warning. + break; + } + + return ext; +} + + +bool TREE_PROJECT_FRAME::AddItemToTreeProject( const wxString& aName, + wxTreeItemId& aRoot, bool aRecurse ) +{ + wxTreeItemId cellule; + + // Check the file type + TreeFileType type = TREE_UNKNOWN; + + // Skip not visible files and dirs + wxFileName fn( aName ); + + // Files/dirs names starting by "." are not visible files under unices. + // Skip them also under Windows + if( fn.GetName().StartsWith( wxT( "." ) ) ) + return false; + + if( wxDirExists( aName ) ) + { + type = TREE_DIRECTORY; + } + else + { + // Filter + wxRegEx reg; + + bool isSchematic = false; + bool addFile = false; + + for( unsigned i = 0; i < m_filters.size(); i++ ) + { + wxCHECK2_MSG( reg.Compile( m_filters[i], wxRE_ICASE ), continue, + wxT( "Regular expression " ) + m_filters[i] + + wxT( " failed to compile." ) ); + + if( reg.Matches( aName ) ) + { + addFile = true; + + if( i==0 ) + isSchematic = true; + + break; + } + } + + if( !addFile ) + return false; + + // only show the schematic if it is a top level schematic. Eeschema + // cannot open a schematic and display it properly unless it starts + // at the top of the hierarchy. The schematic is top level only if + // there is a line in the header saying: + // "Sheet 1 " + // However if the file has the same name as the project, it is always + // shown, because it is expected the root sheet. + // (and to fix an issue (under XP but could exist under other OS), + // when a .sch file is created, the file + // create is sent to the wxFileSystemWatcher, but the file still has 0 byte + // so it cannot detected as root sheet + // This is an ugly fix. + if( isSchematic ) + { + wxString fullFileName = aName.BeforeLast( '.' ); + wxString rootName; + TREEPROJECT_ITEM* itemData = GetItemIdData( m_root ); + if( itemData ) + rootName = itemData->GetFileName().BeforeLast( '.' ); + + if( fullFileName != rootName ) + { + char line[128]; // small because we just need a few bytes from the start of a line + FILE* fp; + + fullFileName = aName; + fp = wxFopen( fullFileName, wxT( "rt" ) ); + + if( fp == NULL ) + return false; + + addFile = false; + + // check the first 100 lines for the "Sheet 1" string + for( int i = 0; i<100; ++i ) + { + if( !fgets( line, sizeof(line), fp ) ) + break; + + if( !strncmp( line, "Sheet 1 ", 8 ) ) + { + addFile = true; + break; + } + } + + fclose( fp ); + + if( !addFile ) + return false; // it is a non-top-level schematic + } + } + + for( int i = TREE_PROJECT; i < TREE_MAX; i++ ) + { + wxString ext = GetFileExt( (TreeFileType) i ); + + if( ext == wxT( "" ) ) + continue; + + reg.Compile( wxString::FromAscii( "^.*\\" ) + ext + + wxString::FromAscii( "$" ), wxRE_ICASE ); + + if( reg.Matches( aName ) ) + { + type = (TreeFileType) i; + break; + } + } + } + + // also check to see if it is already there. + wxTreeItemIdValue cookie; + wxTreeItemId kid = m_TreeProject->GetFirstChild( aRoot, cookie ); + + while( kid.IsOk() ) + { + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( itemData ) + { + if( itemData->GetFileName() == aName ) + { + return true; // well, we would have added it, but it is already here! + } + } + + kid = m_TreeProject->GetNextChild( aRoot, cookie ); + } + + // Append the item (only appending the filename not the full path): + wxString file = wxFileNameFromPath( aName ); + cellule = m_TreeProject->AppendItem( aRoot, file ); + TREEPROJECT_ITEM* data = new TREEPROJECT_ITEM( type, aName, m_TreeProject ); + + m_TreeProject->SetItemData( cellule, data ); + data->SetState( 0 ); + + // Mark root files (files which have the same aName as the project) + wxFileName project( m_Parent->GetProjectFileName() ); + wxFileName currfile( file ); + + if( currfile.GetName().CmpNoCase( project.GetName() ) == 0 ) + data->SetRootFile( true ); + else + data->SetRootFile( false ); + + // This section adds dirs and files found in the subdirs + // in this case AddFile is recursive, but for the first level only. + if( TREE_DIRECTORY == type && aRecurse ) + { + wxDir dir( aName ); + + if( dir.IsOpened() ) // protected dirs will not open properly. + { + wxString dir_filename; + + data->SetPopulated( true ); + + if( dir.GetFirst( &dir_filename ) ) + { + do // Add name in tree, but do not recurse + { + wxString path = aName + wxFileName::GetPathSeparator() + dir_filename; + AddItemToTreeProject( path, cellule, false ); + } while( dir.GetNext( &dir_filename ) ); + } + } + + // Sort filenames by alphabetic order + m_TreeProject->SortChildren( cellule ); + } + + return true; +} + + +void TREE_PROJECT_FRAME::ReCreateTreePrj() +{ + wxTreeItemId rootcellule; + bool prjOpened = false; + wxString pro_dir = m_Parent->GetProjectFileName(); + + if( !m_TreeProject ) + m_TreeProject = new TREEPROJECTFILES( this ); + else + m_TreeProject->DeleteAllItems(); + + if( !pro_dir ) // This is empty from TREE_PROJECT_FRAME constructor + return; + + wxFileName fn = pro_dir; + + if( !fn.IsOk() ) + { + fn.Clear(); + fn.SetPath( wxStandardPaths::Get().GetDocumentsDir() ); + fn.SetName( NAMELESS_PROJECT ); + fn.SetExt( ProjectFileExtension ); + } + + prjOpened = fn.FileExists(); + + // root tree: + m_root = rootcellule = m_TreeProject->AddRoot( fn.GetFullName(), + TREE_PROJECT - 1, + TREE_PROJECT - 1 ); + + m_TreeProject->SetItemBold( rootcellule, true ); + + m_TreeProject->SetItemData( rootcellule, + new TREEPROJECT_ITEM( TREE_PROJECT, + fn.GetFullPath(), + m_TreeProject ) ); + + // Now adding all current files if available + if( prjOpened ) + { + wxString pro_dir = wxPathOnly( m_Parent->GetProjectFileName() ); + wxDir dir( pro_dir ); + + if( dir.IsOpened() ) // protected dirs will not open, see "man opendir()" + { + wxString filename; + bool cont = dir.GetFirst( &filename ); + + while( cont ) + { + if( filename != fn.GetFullName() ) + { + wxString name = dir.GetName() + wxFileName::GetPathSeparator() + filename; + AddItemToTreeProject( name, m_root ); + } + + cont = dir.GetNext( &filename ); + } + } + } + else + { + m_TreeProject->AppendItem( m_root, wxT( "Empty project" ) ); + } + + m_TreeProject->Expand( rootcellule ); + + // Sort filenames by alphabetic order + m_TreeProject->SortChildren( m_root ); +} + + +void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event ) +{ + int tree_id; + TREEPROJECT_ITEM* tree_data; + wxString fullFileName; + wxTreeItemId curr_item = Event.GetItem(); + + // Ensure item is selected (Under Windows right click does not select the item) + m_TreeProject->SelectItem( curr_item ); + + tree_data = GetSelectedData(); + + if( !tree_data ) + return; + + tree_id = tree_data->GetType(); + fullFileName = tree_data->GetFileName(); + + wxMenu popupMenu; + + switch( tree_id ) + { + case TREE_PROJECT: + AddMenuItem( &popupMenu, ID_PROJECT_NEWDIR, + _( "New D&irectory" ), + _( "Create a New Directory" ), + KiBitmap( directory_xpm ) ); + break; + + case TREE_DIRECTORY: + AddMenuItem( &popupMenu, ID_PROJECT_NEWDIR, + _( "New D&irectory" ), + _( "Create a New Directory" ), + KiBitmap( directory_xpm ) ); + AddMenuItem( &popupMenu, ID_PROJECT_DELETE, + _( "&Delete Directory" ), + _( "Delete the Directory and its content" ), + KiBitmap( delete_xpm ) ); + break; + + default: + AddMenuItem( &popupMenu, ID_PROJECT_TXTEDIT, + _( "&Edit in a text editor" ), + _( "Open the file in a Text Editor" ), + KiBitmap( icon_txt_xpm ) ); + AddMenuItem( &popupMenu, ID_PROJECT_RENAME, + _( "&Rename file" ), + _( "Rename file" ), + KiBitmap( right_xpm ) ); + AddMenuItem( &popupMenu, ID_PROJECT_DELETE, + _( "&Delete File" ), + _( "Delete the Directory and its content" ), + KiBitmap( delete_xpm ) ); + break; + } + + PopupMenu( &popupMenu ); +} + + +void TREE_PROJECT_FRAME::OnOpenSelectedFileWithTextEditor( wxCommandEvent& event ) +{ + TREEPROJECT_ITEM* tree_data = GetSelectedData(); + + if( !tree_data ) + return; + + if( tree_data->GetType() == TREE_DIRECTORY ) + return; + + wxString fullFileName = tree_data->GetFileName(); + AddDelimiterString( fullFileName ); + wxString editorname = Pgm().GetEditorName(); + + if( !editorname.IsEmpty() ) + ExecuteFile( this, editorname, fullFileName ); +} + + +void TREE_PROJECT_FRAME::OnDeleteFile( wxCommandEvent& ) +{ + TREEPROJECT_ITEM* tree_data = GetSelectedData(); + + if( !tree_data ) + return; + + tree_data->Delete(); +} + + +void TREE_PROJECT_FRAME::OnRenameFile( wxCommandEvent& ) +{ + wxTreeItemId curr_item = m_TreeProject->GetSelection(); + TREEPROJECT_ITEM* tree_data = GetSelectedData(); + + if( !tree_data ) + return; + + wxString buffer = m_TreeProject->GetItemText( curr_item ); + wxString msg = wxString::Format( + _( "Change filename: '%s'" ), + GetChars( tree_data->GetFileName() ) ); + + wxTextEntryDialog dlg( this, msg, _( "Change filename" ), buffer ); + + if( dlg.ShowModal() != wxID_OK ) + return; // canceled by user + + buffer = dlg.GetValue(); + buffer.Trim( true ); + buffer.Trim( false ); + + if( buffer.IsEmpty() ) + return; // empty file name not allowed + + if( tree_data->Rename( buffer, true ) ) + m_TreeProject->SetItemText( curr_item, buffer ); +} + + +void TREE_PROJECT_FRAME::OnSelect( wxTreeEvent& Event ) +{ + TREEPROJECT_ITEM* tree_data = GetSelectedData(); + + if( !tree_data ) + return; + + tree_data->Activate( this ); +} + + +void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) +{ + wxTreeItemId itemId = Event.GetItem(); + TREEPROJECT_ITEM* tree_data = GetItemIdData( itemId ); + + if( !tree_data ) + return; + + if( tree_data->GetType() != TREE_DIRECTORY ) + return; + + // explore list of non populated subdirs, and populate them + wxTreeItemIdValue cookie; + wxTreeItemId kid = m_TreeProject->GetFirstChild( itemId, cookie ); + + bool subdir_populated = false; + + for( ; kid.IsOk(); kid = m_TreeProject->GetNextChild( itemId, cookie ) ) + { + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( !itemData || itemData->GetType() != TREE_DIRECTORY ) + continue; + + if( itemData->IsPopulated() ) + continue; + + wxString fileName = itemData->GetFileName(); + wxDir dir( fileName ); + + if( dir.IsOpened() ) + { + wxString dir_filename; + + if( dir.GetFirst( &dir_filename ) ) + { + do // Add name to tree item, but do not recurse in subdirs: + { + wxString name = fileName + wxFileName::GetPathSeparator() + dir_filename; + AddItemToTreeProject( name, kid, false ); + } while( dir.GetNext( &dir_filename ) ); + } + + itemData->SetPopulated( true ); // set state to populated + subdir_populated = true; + } + + // Sort filenames by alphabetic order + m_TreeProject->SortChildren( kid ); + } + + if( subdir_populated ) + { + #ifndef __WINDOWS__ + FileWatcherReset(); + #endif + } +} + + +TREEPROJECT_ITEM* TREE_PROJECT_FRAME::GetSelectedData() +{ + return dynamic_cast<TREEPROJECT_ITEM*>( m_TreeProject->GetItemData + ( m_TreeProject->GetSelection() ) ); +} + + +TREEPROJECT_ITEM* TREE_PROJECT_FRAME::GetItemIdData( wxTreeItemId aId ) +{ + return dynamic_cast<TREEPROJECT_ITEM*>( m_TreeProject->GetItemData( aId ) ); +} + + +wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir ) +{ + wxString prj_dir = wxPathOnly( m_Parent->GetProjectFileName() ); + + // If the subdir is the current working directory, return m_root + // in main list: + if( prj_dir == aSubDir ) + return m_root; + + // The subdir is in the main tree or in a subdir: Locate it + wxTreeItemIdValue cookie; + wxTreeItemId root_id = m_root; + std::stack < wxTreeItemId > subdirs_id; + + wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie ); + + while( 1 ) + { + if( ! kid.IsOk() ) + { + if( subdirs_id.empty() ) // all items were explored + { + root_id = kid; // Not found: return an invalid wxTreeItemId + break; + } + else + { + root_id = subdirs_id.top(); + subdirs_id.pop(); + kid = m_TreeProject->GetFirstChild( root_id, cookie ); + + if( ! kid.IsOk() ) + continue; + } + } + + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( itemData && ( itemData->GetType() == TREE_DIRECTORY ) ) + { + if( itemData->GetFileName() == aSubDir ) // Found! + { + root_id = kid; + break; + } + + // kid is a subdir, push in list to explore it later + if( itemData->IsPopulated() ) + subdirs_id.push( kid ); + } + + kid = m_TreeProject->GetNextChild( root_id, cookie ); + } + + return root_id; +} + + +void TREE_PROJECT_FRAME::OnFileSystemEvent( wxFileSystemWatcherEvent& event ) +{ + wxFileName pathModified = event.GetPath(); + wxString subdir = pathModified.GetPath(); + wxString fn = pathModified.GetFullPath(); + + switch( event.GetChangeType() ) + { + case wxFSW_EVENT_DELETE: + break; + + case wxFSW_EVENT_CREATE: + break; + + case wxFSW_EVENT_RENAME: + break; + + case wxFSW_EVENT_MODIFY: + case wxFSW_EVENT_ACCESS: + default: + return; + } + + wxTreeItemId root_id = findSubdirTreeItem( subdir ); + + if( !root_id.IsOk() ) + return; + + wxTreeItemIdValue cookie; // dummy variable needed by GetFirstChild() + wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie ); + + switch( event.GetChangeType() ) + { + case wxFSW_EVENT_CREATE: + AddItemToTreeProject( pathModified.GetFullPath(), root_id, false ); + break; + + case wxFSW_EVENT_DELETE: + while( kid.IsOk() ) + { + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( itemData && itemData->GetFileName() == fn ) + { + m_TreeProject->Delete( kid ); + return; + } + kid = m_TreeProject->GetNextChild( root_id, cookie ); + } + break; + + case wxFSW_EVENT_RENAME : + { + wxFileName newpath = event.GetNewPath(); + wxString newfn = newpath.GetFullPath(); + + while( kid.IsOk() ) + { + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( itemData && itemData->GetFileName() == fn ) + { + m_TreeProject->Delete( kid ); + break; + } + + kid = m_TreeProject->GetNextChild( root_id, cookie ); + } + + AddItemToTreeProject( newfn, root_id, false ); + } + break; + } + + // Sort filenames by alphabetic order + m_TreeProject->SortChildren( root_id ); +} + + +void TREE_PROJECT_FRAME::FileWatcherReset() +{ + // Prepare file watcher: + if( m_watcher ) + { + m_watcher->RemoveAll(); + } + else + { + m_watcher = new wxFileSystemWatcher(); + m_watcher->SetOwner( this ); + } + + // Add directories which should be monitored. + // under windows, we add the curr dir and all subdirs + // under unix, we add only the curr dir and the populated subdirs + // see http://docs.wxwidgets.org/trunk/classwx_file_system_watcher.htm + // under unix, the file watcher needs more work to be efficient + // moreover, under wxWidgets 2.9.4, AddTree does not work properly. + + // We can see wxString under a debugger, not a wxFileName + wxString prj_dir = wxPathOnly( m_Parent->GetProjectFileName() ); + wxFileName fn; + fn.AssignDir( prj_dir ); + fn.DontFollowLink(); + +#ifdef __WINDOWS__ + m_watcher->AddTree( fn ); +#else + m_watcher->Add( fn ); + + // Add subdirs + wxTreeItemIdValue cookie; + wxTreeItemId root_id = m_root; + + std::stack < wxTreeItemId > subdirs_id; + + wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie ); + + while( 1 ) + { + if( !kid.IsOk() ) + { + if( subdirs_id.empty() ) // all items were explored + break; + else + { + root_id = subdirs_id.top(); + subdirs_id.pop(); + kid = m_TreeProject->GetFirstChild( root_id, cookie ); + + if( !kid.IsOk() ) + continue; + } + } + + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( itemData && itemData->GetType() == TREE_DIRECTORY ) + { + // we can see wxString under a debugger, not a wxFileName + wxString path = itemData->GetFileName(); + + wxLogDebug( "%s: add '%s'\n", __func__, TO_UTF8( path ) ); + + if( wxFileName::IsDirReadable( path ) ) // linux whines about watching protected dir + { + fn.AssignDir( path ); + m_watcher->Add( fn ); + + // if kid is a subdir, push in list to explore it later + if( itemData->IsPopulated() && m_TreeProject->GetChildrenCount( kid ) ) + subdirs_id.push( kid ); + } + } + + kid = m_TreeProject->GetNextChild( root_id, cookie ); + } +#endif + +#if defined(DEBUG) && 1 + wxArrayString paths; + m_watcher->GetWatchedPaths( &paths ); + wxLogDebug( "%s: watched paths:", __func__ ); + + for( unsigned ii = 0; ii < paths.GetCount(); ii++ ) + wxLogDebug( " %s\n", TO_UTF8( paths[ii] ) ); +#endif +} + + +void KICAD_MANAGER_FRAME::OnChangeWatchedPaths( wxCommandEvent& aEvent ) +{ + m_LeftWin->FileWatcherReset(); +} diff --git a/kicad/tree_project_frame.h b/kicad/tree_project_frame.h new file mode 100644 index 0000000..908e8a3 --- /dev/null +++ b/kicad/tree_project_frame.h @@ -0,0 +1,184 @@ +/** + * @file tree_project_frame.h + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2012 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 + */ + +#ifndef TREEPRJ_FRAME_H +#define TREEPRJ_FRAME_H + +#include <kicad.h> +#include <wx/fswatcher.h> + + +class TREEPROJECT_ITEM; + +/** class TREE_PROJECT_FRAME + * Window to display the tree files + */ +class TREE_PROJECT_FRAME : public wxSashLayoutWindow +{ + friend class TREEPROJECT_ITEM; +public: + KICAD_MANAGER_FRAME* m_Parent; + TREEPROJECTFILES* m_TreeProject; + +private: + wxTreeItemId m_root; + std::vector<wxString> m_filters; + wxFileSystemWatcher* m_watcher; // file system watcher (since wxWidgets 2.9.2) + +public: + TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ); + ~TREE_PROJECT_FRAME(); + + /** + * Create or modify the tree showing project file names + */ + void ReCreateTreePrj(); + + /** + * Reinit the watched paths + * Should be called after opening a new project to + * rebuild the list of watched paths. + * Should be called *atfer* the main loop event handler is started + */ + void FileWatcherReset(); + +protected: + static wxString GetFileExt( TreeFileType type ); + static wxString GetFileWildcard( TreeFileType type ); + + /** + * Function GetSelectedData + * return the item data from item currently selected (highlighted) + * Note this is not necessary the "clicked" item, + * because when expanding, collapsing an item this item is not selected + */ + TREEPROJECT_ITEM* GetSelectedData(); + + /** + * Function GetItemIdData + * return the item data corresponding to a wxTreeItemId identifier + * @param aId = the wxTreeItemId identifier. + * @return a TREEPROJECT_ITEM pointer correspondinfg to item id aId + */ + TREEPROJECT_ITEM* GetItemIdData( wxTreeItemId aId ); + +private: + /** + * Called on a double click on an item + */ + void OnSelect( wxTreeEvent& Event ); + + /** + * Called on a click on the + or - button of an item with children + */ + void OnExpand( wxTreeEvent& Event ); + + /** + * Called on a right click on an item + */ + void OnRight( wxTreeEvent& Event ); + + /** + * Function OnOpenSelectedFileWithTextEditor + * Called via the popup menu, when right clicking on a file name + * Call the text editor to open the selected file + * in the tree project + */ + void OnOpenSelectedFileWithTextEditor( wxCommandEvent& event ); + + /** + * Function OnDeleteFile + * Called via the popup menu, when right clicking on a file name + * or a directory name to delete the selected file or directory + * in the tree project + */ + void OnDeleteFile( wxCommandEvent& event ); + + /** + * Function OnRenameFile + * Called via the popup menu, when right clicking on a file name + * or a directory name to rename the selected file or directory + * in the tree project + */ + void OnRenameFile( wxCommandEvent& event ); + + /** + * Function OnCreateNewDirectory + * Creates a new subdirectory inside the current kicad project directory + * the user is prompted to enter a directory name + */ + void OnCreateNewDirectory( wxCommandEvent& event ); + + void ClearFilters() + { + m_filters.clear(); + } + + const std::vector<wxString>& GetFilters() + { + return m_filters; + } + + void RemoveFilter( const wxString& filter ); + + /** + * Function AddItemToTreeProject + * @brief Add the file or directory aName to the project tree + * @param aName = the filename or the directory name to add in tree + * @param aRoot = the wxTreeItemId item where to add sub tree items + * @param aRecurse = true to add file or subdir names to the current tree item + * false to stop file add. + * @return true if the file (or directory) is added. + */ + bool AddItemToTreeProject( const wxString& aName, + wxTreeItemId& aRoot, + bool aRecurse = true ); + + /** + * Function findSubdirTreeItem + * searches for the item in tree project which is the + * node of the subdirectory aSubDir + * @param aSubDir = the directory to find in tree + * @return the opaque reference to the tree item. + * if not found, return an invalid tree item. + * therefore wxTreeItemId::IsOk should be used to test + * the returned value + */ + wxTreeItemId findSubdirTreeItem( const wxString& aSubDir ); + + /** + * called when a file or directory is modified/created/deleted + * The tree project is modified when a file or directory + * is created/deleted/renamed to reflect the file change + */ + void OnFileSystemEvent( wxFileSystemWatcherEvent& event ); + + DECLARE_EVENT_TABLE() +}; + +#endif // TREEPRJ_FRAME_H |