7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-18 18:29:17 +00:00

Resync with main branch r6482

This commit is contained in:
Cirilo Bernardo 2016-01-16 19:10:53 +11:00
commit e185b29baa
99 changed files with 2820 additions and 1180 deletions
CMakeModules
bitmap2component
common
eeschema
include
kicad
pcbnew
plugins/3d/vrml
utils/idftools

View File

@ -0,0 +1,342 @@
#.rst:
# FindOpenSSL
# -----------
#
# Try to find the OpenSSL encryption library
#
# Once done this will define
#
# ::
#
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
#
#
#
# Read-Only variables:
#
# ::
#
# OPENSSL_FOUND - system has the OpenSSL library
# OPENSSL_INCLUDE_DIR - the OpenSSL include directory
# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
# OPENSSL_VERSION - This is set to $major.$minor.$revision$path (eg. 0.9.8s)
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
# Copyright 2009-2011 Mathieu Malaterre <mathieu.malaterre@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
if (UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(_OPENSSL QUIET openssl)
endif ()
if (WIN32)
# http://www.slproweb.com/products/Win32OpenSSL.html
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
ENV OPENSSL_ROOT_DIR
)
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
set(_OPENSSL_ROOT_PATHS
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-Win32"
"${_programfiles}/OpenSSL-Win64"
"C:/OpenSSL/"
"C:/OpenSSL-Win32/"
"C:/OpenSSL-Win64/"
)
unset(_programfiles)
else ()
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
)
endif ()
set(_OPENSSL_ROOT_HINTS_AND_PATHS
HINTS ${_OPENSSL_ROOT_HINTS}
PATHS ${_OPENSSL_ROOT_PATHS}
)
find_path(OPENSSL_INCLUDE_DIR
NAMES
openssl/ssl.h
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_INCLUDEDIR}
PATH_SUFFIXES
include
)
if(WIN32 AND NOT CYGWIN)
if(MSVC)
# /MD and /MDd are the standard values - if someone wants to use
# others, the libnames have to change here too
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
# TODO: handle /MT and static lib
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
# * MD for dynamic-release
# * MDd for dynamic-debug
# * MT for static-release
# * MTd for static-debug
# Implementation details:
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
# libeay32MD.lib is identical to ../libeay32.lib, and
# ssleay32MD.lib is identical to ../ssleay32.lib
find_library(LIB_EAY_DEBUG
NAMES
libeay32MDd
libeay32d
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
find_library(LIB_EAY_RELEASE
NAMES
libeay32MD
libeay32
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
find_library(SSL_EAY_DEBUG
NAMES
ssleay32MDd
ssleay32d
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
find_library(SSL_EAY_RELEASE
NAMES
ssleay32MD
ssleay32
ssl
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
set(LIB_EAY_LIBRARY_RELEASE "${LIB_EAY_RELEASE}")
set(SSL_EAY_LIBRARY_DEBUG "${SSL_EAY_DEBUG}")
set(SSL_EAY_LIBRARY_RELEASE "${SSL_EAY_RELEASE}")
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
select_library_configurations(LIB_EAY)
select_library_configurations(SSL_EAY)
mark_as_advanced(LIB_EAY_LIBRARY_DEBUG LIB_EAY_LIBRARY_RELEASE
SSL_EAY_LIBRARY_DEBUG SSL_EAY_LIBRARY_RELEASE)
set( OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY} )
elseif(MINGW)
message( STATUS "Searching for OpenSSL in MinGW." )
# same player, for MinGW
set(LIB_EAY_NAMES libeay32)
set(SSL_EAY_NAMES ssleay32)
list(APPEND LIB_EAY_NAMES crypto)
list(APPEND SSL_EAY_NAMES ssl)
find_library(LIB_EAY
NAMES
${LIB_EAY_NAMES}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"lib/MinGW"
# Do not search system path. Otherwise the DLL will be found rather than the link library.
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH
)
find_library(SSL_EAY
NAMES
${SSL_EAY_NAMES}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"lib/MinGW"
# Do not search system path. Otherwise the DLL will be found rather than the link library.
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH
)
mark_as_advanced(SSL_EAY LIB_EAY)
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
unset(LIB_EAY_NAMES)
unset(SSL_EAY_NAMES)
else()
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
find_library(LIB_EAY
NAMES
libeay32
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
PATH_SUFFIXES
lib
)
find_library(SSL_EAY
NAMES
ssleay32
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
PATH_SUFFIXES
lib
)
mark_as_advanced(SSL_EAY LIB_EAY)
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
endif()
else()
find_library(OPENSSL_SSL_LIBRARY
NAMES
ssl
ssleay32
ssleay32MD
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
PATH_SUFFIXES
lib
)
find_library(OPENSSL_CRYPTO_LIBRARY
NAMES
crypto
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
PATH_SUFFIXES
lib
)
mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
# compat defines
set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
endif()
function(from_hex HEX DEC)
string(TOUPPER "${HEX}" HEX)
set(_res 0)
string(LENGTH "${HEX}" _strlen)
while (_strlen GREATER 0)
math(EXPR _res "${_res} * 16")
string(SUBSTRING "${HEX}" 0 1 NIBBLE)
string(SUBSTRING "${HEX}" 1 -1 HEX)
if (NIBBLE STREQUAL "A")
math(EXPR _res "${_res} + 10")
elseif (NIBBLE STREQUAL "B")
math(EXPR _res "${_res} + 11")
elseif (NIBBLE STREQUAL "C")
math(EXPR _res "${_res} + 12")
elseif (NIBBLE STREQUAL "D")
math(EXPR _res "${_res} + 13")
elseif (NIBBLE STREQUAL "E")
math(EXPR _res "${_res} + 14")
elseif (NIBBLE STREQUAL "F")
math(EXPR _res "${_res} + 15")
else()
math(EXPR _res "${_res} + ${NIBBLE}")
endif()
string(LENGTH "${HEX}" _strlen)
endwhile()
set(${DEC} ${_res} PARENT_SCOPE)
endfunction()
if (OPENSSL_INCLUDE_DIR)
if (_OPENSSL_VERSION)
set(OPENSSL_VERSION "${_OPENSSL_VERSION}")
elseif(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
# The status gives if this is a developer or prerelease and is ignored here.
# Major, minor, and fix directly translate into the version numbers shown in
# the string. The patch field translates to the single character suffix that
# indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
# on.
message(STATUS "OPENSSL_VERSION_STR=${openssl_version_str}")
string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
"\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
# 96 is the ASCII code of 'a' minus 1
math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
unset(_tmp)
# Once anyone knows how OpenSSL would call the patch versions beyond 'z'
# this should be updated to handle that, too. This has not happened yet
# so it is simply ignored here for now.
string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
endif ()
set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
endif ()
endif ()
include(FindPackageHandleStandardArgs)
if (OPENSSL_VERSION)
find_package_handle_standard_args(OpenSSL
REQUIRED_VARS
OPENSSL_LIBRARIES
OPENSSL_INCLUDE_DIR
VERSION_VAR
OPENSSL_VERSION
FAIL_MESSAGE
"Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
)
else ()
find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
OPENSSL_LIBRARIES
OPENSSL_INCLUDE_DIR
)
endif ()
mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)

View File

@ -2,7 +2,6 @@
include_directories( BEFORE ${INC_BEFORE} )
include_directories(
../potrace
../common
../polygon
${INC_AFTER}
)

View File

@ -30,19 +30,19 @@
#include <confirm.h>
#include <gestfich.h>
#include <wildcards_and_files_ext.h>
#include <bitmap2cmp_gui_base.h>
#include <bitmap2component.h>
#include <potracelib.h>
#include <bitmap_io.h>
#include <colors_selection.h>
#include <build_version.h>
#include <menus_helpers.h>
#include <kiway.h>
#include <kiface_i.h>
#include <potracelib.h>
#include "bitmap2component.h"
#include "bitmap2cmp_gui_base.h"
#define KEYWORD_FRAME_POSX wxT( "Bmconverter_Pos_x" )
#define KEYWORD_FRAME_POSY wxT( "Bmconverter_Pos_y" )

View File

@ -21,28 +21,24 @@
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <cmath>
#include <algorithm> // std::max
// For some unknown reasons, polygon.hpp should be included first
#include <boost/polygon/polygon.hpp>
#include <wx/wx.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <cmath>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <layers_id_colors_and_visibility.h>
#include <common.h>
#include <bitmap2component.h>
#include <geometry/shape_poly_set.h>
#include <layers_id_colors_and_visibility.h>
// include this after shape_poly_set.h to avoid redefinition of min, max ...
#include <potracelib.h>
#include "bitmap2component.h"
/* free a potrace bitmap */
static void bm_free( potrace_bitmap_t* bm )
{
@ -60,14 +56,14 @@ static void bm_free( potrace_bitmap_t* bm )
class BITMAPCONV_INFO
{
public:
enum OUTPUT_FMT_ID m_Format; // File format
enum OUTPUT_FMT_ID m_Format; // File format
int m_PixmapWidth;
int m_PixmapHeight; // the bitmap size in pixels
double m_ScaleX;
double m_ScaleY; // the conversion scale
potrace_path_t* m_Paths; // the list of paths, from potrace (list of lines and bezier curves)
FILE* m_Outfile; // File to create
const char * m_CmpName; // The string used as cmp/footprint name
const char * m_CmpName; // The string used as cmp/footprint name
public:
BITMAPCONV_INFO();

View File

@ -1,6 +1,7 @@
include_directories( BEFORE ${INC_BEFORE} )
include_directories(
./dialogs
./widgets
./dialog_about
${CAIRO_INCLUDE_DIR}
${GLEW_INCLUDE_DIR}
@ -12,6 +13,12 @@ include_directories(
${INC_AFTER}
)
if( NOT APPLE ) # windows and linux use openssl under curl
find_package( OpenSSL REQUIRED )
endif()
# Generate header files containing shader programs
# Order of input files is significant
add_custom_command(
@ -138,6 +145,9 @@ set( COMMON_ABOUT_DLG_SRCS
dialog_about/AboutDialog_main.cpp
dialog_about/dialog_about.cpp
dialog_about/dialog_about_base.cpp
)
set( COMMON_DLG_SRCS
dialogs/dialog_display_info_HTML_base.cpp
dialogs/dialog_exit_base.cpp
dialogs/dialog_image_editor.cpp
@ -154,6 +164,10 @@ set( COMMON_ABOUT_DLG_SRCS
dialogs/wx_html_report_panel.cpp
)
set( COMMON_WIDGET_SRCS
widgets/widget_hotkey_list.cpp
)
set( COMMON_PAGE_LAYOUT_SRCS
page_layout/title_block_shapes.cpp
page_layout/class_worksheet_dataitem.cpp
@ -167,6 +181,8 @@ set( COMMON_PAGE_LAYOUT_SRCS
set( COMMON_SRCS
${LIB_KICAD_SRCS}
${COMMON_ABOUT_DLG_SRCS}
${COMMON_DLG_SRCS}
${COMMON_WIDGET_SRCS}
${COMMON_PAGE_LAYOUT_SRCS}
base_struct.cpp
basicframe.cpp
@ -285,7 +301,8 @@ add_dependencies( common lib-dependencies )
add_dependencies( common version_header )
target_link_libraries( common
${Boost_LIBRARIES}
# ${CURL_LIBRARIES} we dynamically link to this ON DEMAND, not at load time
${CURL_LIBRARIES}
${OPENSSL_LIBRARIES} # empty on Apple
)

View File

@ -28,7 +28,6 @@
* @brief EDA_BASE_FRAME class implementation.
*/
#include <kicad_curl/kicad_curl.h> /* Include before any wx file */
#include <wx/aboutdlg.h>
#include <wx/fontdlg.h>
#include <wx/clipbrd.h>
@ -40,7 +39,6 @@
#include <fctsys.h>
#include <pgm_base.h>
#include <kiface_i.h>
#include <online_help.h>
#include <id.h>
#include <eda_doc.h>
#include <wxstruct.h>
@ -574,8 +572,6 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event )
<< ( BOOST_VERSION / 100 % 1000 ) << wxT( "." )
<< ( BOOST_VERSION % 100 ) << wxT( "\n" );
msg_version << KICAD_CURL::GetSimpleVersion() << wxT( "\n" );
msg_version << wxT( " USE_WX_GRAPHICS_CONTEXT=" );
#ifdef USE_WX_GRAPHICS_CONTEXT
msg_version << wxT( "ON\n" );

View File

@ -23,7 +23,6 @@
*/
#include <bin_mod.h>
#include <online_help.h>
#include <common.h>

View File

@ -21,320 +21,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <algorithm>
#include <fctsys.h>
#include <pgm_base.h>
#include <common.h>
#include <confirm.h>
#include <dialog_hotkeys_editor.h>
class DIALOG_HOTKEY_CLIENT_DATA : public wxClientData
{
EDA_HOTKEY m_hotkey;
wxString m_section_tag;
public:
DIALOG_HOTKEY_CLIENT_DATA( const EDA_HOTKEY& aHotkey, const wxString& aSectionTag )
: m_hotkey( aHotkey ), m_section_tag( aSectionTag ) {}
EDA_HOTKEY& GetHotkey() { return m_hotkey; }
wxString GetSectionTag() const { return m_section_tag; }
};
HOTKEY_LIST_CTRL::HOTKEY_LIST_CTRL( wxWindow *aParent, const HOTKEYS_SECTIONS& aSections ) :
wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
m_sections( aSections )
{
AppendColumn( _( "Command" ) );
AppendColumn( _( "Hotkey" ) );
SetColumnWidth( 1, 100 );
Bind( wxEVT_CHAR, &HOTKEY_LIST_CTRL::OnChar, this );
}
void HOTKEY_LIST_CTRL::DeselectRow( int aRow )
{
wxASSERT( aRow >= 0 && aRow < (int)m_items.size() );
Unselect( m_items[aRow] );
}
void HOTKEY_LIST_CTRL::OnChar( wxKeyEvent& aEvent )
{
DIALOG_HOTKEY_CLIENT_DATA* data = GetSelHKClientData();
if( data )
{
long key = aEvent.GetKeyCode();
switch( key )
{
case WXK_ESCAPE:
UnselectAll();
break;
default:
if( key >= 'a' && key <= 'z' ) // convert to uppercase
key = key + ('A' - 'a');
// Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL)
// to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z'
if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
key += 'A' - 1;
/* Disallow shift for keys that have two keycodes on them (e.g. number and
* punctuation keys) leaving only the "letter keys" of A-Z.
* Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
* and Ctrl-( and Ctrl-5 (FR layout).
* Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
*/
bool keyIsLetter = key >= 'A' && key <= 'Z';
if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) )
key |= GR_KB_SHIFT;
if( aEvent.ControlDown() )
key |= GR_KB_CTRL;
if( aEvent.AltDown() )
key |= GR_KB_ALT;
// See if this key code is handled in hotkeys names list
bool exists;
KeyNameFromKeyCode( key, &exists );
if( exists && data->GetHotkey().m_KeyCode != key )
{
wxString tag = data->GetSectionTag();
bool canUpdate = ResolveKeyConflicts( key, tag );
if( canUpdate )
{
data->GetHotkey().m_KeyCode = key;
}
// Remove selection
UnselectAll();
}
}
}
UpdateFromClientData();
}
DIALOG_HOTKEY_CLIENT_DATA* HOTKEY_LIST_CTRL::GetSelHKClientData()
{
return GetHKClientData( GetSelection() );
}
DIALOG_HOTKEY_CLIENT_DATA* HOTKEY_LIST_CTRL::GetHKClientData( wxTreeListItem aItem )
{
if( aItem.IsOk() )
{
wxClientData* data = GetItemData( aItem );
if( !data )
return NULL;
DIALOG_HOTKEY_CLIENT_DATA* hkdata = static_cast<DIALOG_HOTKEY_CLIENT_DATA*>( data );
return hkdata;
}
else
{
return NULL;
}
}
void HOTKEY_LIST_CTRL::LoadSection( struct EDA_HOTKEY_CONFIG* aSection )
{
HOTKEY_LIST list;
EDA_HOTKEY** info_ptr;
for( info_ptr = aSection->m_HK_InfoList; *info_ptr; info_ptr++ )
{
EDA_HOTKEY info = **info_ptr;
list.push_back( info );
}
m_hotkeys.push_back( list );
}
void HOTKEY_LIST_CTRL::UpdateFromClientData()
{
for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
{
DIALOG_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i );
if( !hkdata )
continue;
EDA_HOTKEY& hk = hkdata->GetHotkey();
wxString name = wxGetTranslation( hk.m_InfoMsg );
wxString key = KeyNameFromKeyCode( hk.m_KeyCode );
SetItemText( i, 0, name );
SetItemText( i, 1, key );
}
}
bool HOTKEY_LIST_CTRL::TransferDataToControl()
{
Freeze();
DeleteAllItems();
m_items.clear();
m_hotkeys.clear();
HOTKEYS_SECTIONS::iterator sec_it;
size_t sec_index = 0;
for( sec_it = m_sections.begin(); sec_it != m_sections.end(); ++sec_it, ++sec_index )
{
LoadSection( sec_it->second );
wxString section_tag = *( sec_it->second->m_SectionTag );
// Create parent item
wxTreeListItem parent = AppendItem( GetRootItem(), sec_it->first );
HOTKEY_LIST& each_list = m_hotkeys[sec_index];
HOTKEY_LIST::iterator hk_it;
for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it )
{
wxTreeListItem item = AppendItem( parent, wxEmptyString );
SetItemData( item, new DIALOG_HOTKEY_CLIENT_DATA( &*hk_it, section_tag ) );
m_items.push_back( item );
}
Expand( parent );
}
UpdateFromClientData();
Thaw();
return true;
}
bool HOTKEY_LIST_CTRL::TransferDataFromControl()
{
for( size_t i_sec = 0; i_sec < m_sections.size(); ++i_sec )
{
struct EDA_HOTKEY_CONFIG* section = m_sections[i_sec].second;
for( EDA_HOTKEY** info_ptr = section->m_HK_InfoList; *info_ptr; ++info_ptr )
{
EDA_HOTKEY* info = *info_ptr;
for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
{
DIALOG_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
if( !hkdata )
continue;
EDA_HOTKEY& hk = hkdata->GetHotkey();
if( hk.m_Idcommand == info->m_Idcommand )
{
info->m_KeyCode = hk.m_KeyCode;
break;
}
}
}
}
return true;
}
bool HOTKEY_LIST_CTRL::ResolveKeyConflicts( long aKey, const wxString& aSectionTag )
{
EDA_HOTKEY* conflictingKey = NULL;
EDA_HOTKEY_CONFIG* conflictingSection = NULL;
CheckKeyConflicts( aKey, aSectionTag, &conflictingKey, &conflictingSection );
if( conflictingKey != NULL )
{
wxString info = wxGetTranslation( conflictingKey->m_InfoMsg );
wxString msg = wxString::Format(
_( "<%s> is already assigned to \"%s\" in section \"%s\". Are you sure you want "
"to change its assignment?" ),
KeyNameFromKeyCode( aKey ), GetChars( info ),
*(conflictingSection->m_Title) );
wxMessageDialog dlg( m_parent, msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT );
if( dlg.ShowModal() == wxID_YES )
{
conflictingKey->m_KeyCode = 0;
UpdateFromClientData();
return true;
}
else
{
return false;
}
}
return true;
}
bool HOTKEY_LIST_CTRL::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect )
{
EDA_HOTKEY* conflictingKey = NULL;
struct EDA_HOTKEY_CONFIG* conflictingSection = NULL;
for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
{
DIALOG_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
if( !hkdata )
continue;
EDA_HOTKEY& hk = hkdata->GetHotkey();
wxString tag = hkdata->GetSectionTag();
if( aSectionTag != g_CommonSectionTag
&& tag != g_CommonSectionTag
&& tag != aSectionTag )
continue;
if( aKey == hk.m_KeyCode )
{
conflictingKey = &hk;
// Find the section
HOTKEYS_SECTIONS::iterator it;
for( it = m_sections.begin(); it != m_sections.end(); ++it )
{
if( *it->second->m_SectionTag == tag )
{
conflictingSection = it->second;
break;
}
}
}
}
if( aConfKey )
*aConfKey = conflictingKey;
if( aConfSect )
*aConfSect = conflictingSection;
return conflictingKey == NULL;
}
void InstallHotkeyFrame( EDA_BASE_FRAME* aParent, EDA_HOTKEY_CONFIG* aHotkeys )
{
HOTKEYS_EDITOR_DIALOG dialog( aParent, aHotkeys );
int diag = dialog.ShowModal();
if( diag == wxID_OK )
{
aParent->ReCreateMenuBar();
@ -343,26 +37,18 @@ void InstallHotkeyFrame( EDA_BASE_FRAME* aParent, EDA_HOTKEY_CONFIG* aHotkeys )
}
HOTKEYS_EDITOR_DIALOG::HOTKEYS_EDITOR_DIALOG( EDA_BASE_FRAME* aParent,
EDA_HOTKEY_CONFIG* aHotkeys ) :
HOTKEYS_EDITOR_DIALOG::HOTKEYS_EDITOR_DIALOG( EDA_BASE_FRAME* aParent,
EDA_HOTKEY_CONFIG* aHotkeys ) :
HOTKEYS_EDITOR_DIALOG_BASE( aParent ),
m_parent( aParent ),
m_hotkeys( aHotkeys )
{
EDA_HOTKEY_CONFIG* section;
HOTKEYS_SECTIONS sections;
for( section = m_hotkeys; section->m_HK_InfoList; section++ )
{
HOTKEYS_SECTION sec( wxGetTranslation( *section->m_Title ), section );
sections.push_back( sec );
}
m_hotkeyListCtrl = new HOTKEY_LIST_CTRL( this, sections );
m_mainSizer->Insert( 1, m_hotkeyListCtrl, wxSizerFlags( 1 ).Expand().Border( wxALL, 5 ) );
Layout();
m_hotkeyListCtrl = new WIDGET_HOTKEY_LIST( m_panelHotkeys,
WIDGET_HOTKEY_LIST::GenSections( aHotkeys ) );
m_hotkeyListCtrl->InstallOnPanel( m_panelHotkeys );
m_sdbSizerOK->SetDefault();
Layout();
Center();
}
@ -388,7 +74,7 @@ bool HOTKEYS_EDITOR_DIALOG::TransferDataFromWindow()
return false;
// save the hotkeys
m_parent->WriteHotkeyConfig( m_hotkeys );
GetParent()->WriteHotkeyConfig( m_hotkeys );
return true;
}
@ -398,4 +84,3 @@ void HOTKEYS_EDITOR_DIALOG::ResetClicked( wxCommandEvent& aEvent )
{
m_hotkeyListCtrl->TransferDataToControl();
}

View File

@ -15,10 +15,13 @@ HOTKEYS_EDITOR_DIALOG_BASE::HOTKEYS_EDITOR_DIALOG_BASE( wxWindow* parent, wxWind
m_mainSizer = new wxBoxSizer( wxVERTICAL );
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Select a row and press a new key combination to alter the binding."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Double-click to edit"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1->Wrap( 400 );
m_mainSizer->Add( m_staticText1, 0, wxALL|wxEXPAND, 5 );
m_panelHotkeys = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_mainSizer->Add( m_panelHotkeys, 1, wxEXPAND | wxALL, 5 );
wxBoxSizer* b_buttonsSizer;
b_buttonsSizer = new wxBoxSizer( wxHORIZONTAL );

View File

@ -125,7 +125,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Select a row and press a new key combination to alter the binding.</property>
<property name="label">Double-click to edit</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@ -176,6 +176,86 @@
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">1</property>
<object class="wxPanel" 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_panelHotkeys</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="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">wxTAB_TRAVERSAL</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">wxALIGN_RIGHT|wxEXPAND</property>

View File

@ -20,6 +20,7 @@ class DIALOG_SHIM;
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/panel.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
@ -37,6 +38,7 @@ class HOTKEYS_EDITOR_DIALOG_BASE : public DIALOG_SHIM
protected:
wxBoxSizer* m_mainSizer;
wxStaticText* m_staticText1;
wxPanel* m_panelHotkeys;
wxButton* m_resetButton;
wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK;

View File

@ -147,6 +147,9 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
m_gal->BeginDrawing();
m_gal->ClearScreen( m_painter->GetSettings()->GetBackgroundColor() );
KIGFX::COLOR4D gridColor = static_cast<KIGFX::PCB_RENDER_SETTINGS*> (m_painter->GetSettings())->GetLayerColor( ITEM_GAL_LAYER ( GRID_VISIBLE ) );
m_gal->SetGridColor ( gridColor );
if( m_view->IsDirty() )
{
m_view->ClearTargets();

View File

@ -302,6 +302,12 @@ void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_P
void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount )
{
// A static table to avoid repetitive calculations of the coefficient
// 1.0 - cos( M_PI/aCircleSegmentsCount)
// aCircleSegmentsCount is most of time <= 64 and usually 8, 12, 16, 32
#define SEG_CNT_MAX 64
static double arc_tolerance_factor[SEG_CNT_MAX+1];
ClipperOffset c;
BOOST_FOREACH( const POLYGON& poly, m_polys )
@ -312,7 +318,27 @@ void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount )
PolyTree solution;
c.ArcTolerance = fabs( (double) aFactor ) / M_PI / aCircleSegmentsCount;
// Calculate the arc tolerance (arc error) from the seg count by circle.
// the seg count is nn = M_PI / acos(1.0 - c.ArcTolerance / abs(aFactor))
// see:
// www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm
if( aCircleSegmentsCount < 6 ) // avoid incorrect aCircleSegmentsCount values
aCircleSegmentsCount = 6;
double coeff;
if( aCircleSegmentsCount > SEG_CNT_MAX || arc_tolerance_factor[aCircleSegmentsCount] == 0 )
{
coeff = 1.0 - cos( M_PI/aCircleSegmentsCount);
if( aCircleSegmentsCount <= SEG_CNT_MAX )
arc_tolerance_factor[aCircleSegmentsCount] = coeff;
}
else
coeff = arc_tolerance_factor[aCircleSegmentsCount];
c.ArcTolerance = std::abs( aFactor ) * coeff;
c.Execute( solution, aFactor );

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 2016 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
@ -26,56 +27,106 @@
#include <wx/dynlib.h>
#include <macros.h>
#include <fctsys.h>
#include <kicad_curl/kicad_curl.h>
#include <ki_mutex.h> // MUTEX and MUTLOCK
#include <richio.h>
// These are even more private than class members, and since there is only
// one instance of KICAD_CURL ever, these statics are hidden here to simplify the
// client (API) header file.
static volatile bool s_initialized;
static MUTEX s_lock;
static MUTEX s_lock; // for s_initialized
// Assume that on these platforms libcurl uses OpenSSL
#if defined(__linux__) || defined(_WIN32)
void (CURL_EXTERN * KICAD_CURL::easy_cleanup) ( CURL* curl );
CURL* (CURL_EXTERN * KICAD_CURL::easy_init) ( void );
CURLcode (CURL_EXTERN * KICAD_CURL::easy_perform) ( CURL* curl );
CURLcode (CURL_EXTERN * KICAD_CURL::easy_setopt) ( CURL* curl, CURLoption option, ... );
const char* (CURL_EXTERN * KICAD_CURL::easy_strerror) ( CURLcode );
CURLcode (CURL_EXTERN * KICAD_CURL::global_init) ( long flags );
void (CURL_EXTERN * KICAD_CURL::global_cleanup) ( void );
curl_slist* (CURL_EXTERN * KICAD_CURL::slist_append) ( curl_slist*, const char* );
void (CURL_EXTERN * KICAD_CURL::slist_free_all) ( curl_slist* );
char* (CURL_EXTERN * KICAD_CURL::version) ( void );
curl_version_info_data* (CURL_EXTERN * KICAD_CURL::version_info) (CURLversion);
#include <openssl/crypto.h>
static MUTEX* s_crypto_locks;
struct DYN_LOOKUP
static void lock_callback( int mode, int type, const char* file, int line )
{
const char* name;
void** address;
};
(void)file;
(void)line;
// May need to modify "name" for each platform according to how libcurl is built on
// that platform and the spelling or partial mangling of C function names. On linux
// there is no mangling.
#define DYN_PAIR( basename ) { "curl_" #basename, (void**) &KICAD_CURL::basename }
wxASSERT( s_crypto_locks && unsigned( type ) < unsigned( CRYPTO_num_locks() ) );
//DBG( printf( "%s: mode=0x%x type=%d file=%s line=%d\n", __func__, mode, type, file, line );)
if( mode & CRYPTO_LOCK )
{
s_crypto_locks[ type ].lock();
}
else
{
s_crypto_locks[ type ].unlock();
}
}
const DYN_LOOKUP KICAD_CURL::dyn_funcs[] = {
DYN_PAIR( easy_cleanup ),
DYN_PAIR( easy_init ),
DYN_PAIR( easy_perform ),
DYN_PAIR( easy_setopt ),
DYN_PAIR( easy_strerror ),
DYN_PAIR( global_init ),
DYN_PAIR( global_cleanup ),
DYN_PAIR( slist_append ),
DYN_PAIR( slist_free_all ),
DYN_PAIR( version ),
DYN_PAIR( version_info ),
};
static void init_locks()
{
s_crypto_locks = new MUTEX[ CRYPTO_num_locks() ];
// From http://linux.die.net/man/3/crypto_set_id_callback:
/*
OpenSSL can safely be used in multi-threaded applications provided that at
least two callback functions are set, locking_function and threadid_func.
locking_function(int mode, int n, const char *file, int line) is needed to
perform locking on shared data structures. (Note that OpenSSL uses a number
of global data structures that will be implicitly shared whenever multiple
threads use OpenSSL.) Multi-threaded applications will crash at random if it
is not set.
threadid_func( CRYPTO_THREADID *id) is needed to record the
currently-executing thread's identifier into id. The implementation of this
callback should not fill in id directly, but should use
CRYPTO_THREADID_set_numeric() if thread IDs are numeric, or
CRYPTO_THREADID_set_pointer() if they are pointer-based. If the application
does not register such a callback using CRYPTO_THREADID_set_callback(), then
a default implementation is used - on Windows and BeOS this uses the
system's default thread identifying APIs, and on all other platforms it uses
the address of errno. The latter is satisfactory for thread-safety if and
only if the platform has a thread-local error number facility.
Dick: "sounds like CRYPTO_THREADID_set_callback() is not mandatory on our
2 OpenSSL platforms."
*/
CRYPTO_set_locking_callback( &lock_callback );
}
static void kill_locks()
{
CRYPTO_set_locking_callback( NULL );
delete[] s_crypto_locks;
s_crypto_locks = NULL;
}
#else
inline void init_locks() { /* dummy */ }
inline void kill_locks() { /* dummy */ }
#endif
/// At process termination, using atexit() keeps the CURL stuff out of the
/// singletops and PGM_BASE.
static void at_terminate()
{
KICAD_CURL::Cleanup();
}
void KICAD_CURL::Init()
@ -89,56 +140,14 @@ void KICAD_CURL::Init()
if( !s_initialized )
{
// dynamically load the library.
wxDynamicLibrary dso;
wxString canonicalName = dso.CanonicalizeName( wxT( "curl" ) );
// This is an ugly hack for MinGW builds. We should probably use something
// like objdump to get the actual library file name from the link file.
#if defined( __MINGW32__ )
canonicalName = dso.CanonicalizeName( wxT( "curl-4" ) );
canonicalName = wxT( "lib" ) + canonicalName;
#endif
if( !dso.Load( canonicalName, wxDL_NOW | wxDL_GLOBAL ) )
{
// Failure: error reporting UI was done via wxLogSysError().
std::string msg = StrPrintf( "%s not wxDynamicLibrary::Load()ed",
static_cast< const char *>( canonicalName.mb_str() ) );
THROW_IO_ERROR( msg );
}
// get addresses.
for( unsigned i=0; i < DIM(dyn_funcs); ++i )
{
*dyn_funcs[i].address = dso.GetSymbol( dyn_funcs[i].name );
if( *dyn_funcs[i].address == NULL )
{
// Failure: error reporting UI was done via wxLogSysError().
// No further reporting required here.
std::string msg = StrPrintf( "%s has no function %s",
static_cast<const char*>( canonicalName.mb_str() ),
dyn_funcs[i].name );
THROW_IO_ERROR( msg );
}
}
if( KICAD_CURL::global_init( CURL_GLOBAL_ALL ) != CURLE_OK )
if( curl_global_init( CURL_GLOBAL_ALL ) != CURLE_OK )
{
THROW_IO_ERROR( "curl_global_init() failed." );
}
wxLogDebug( "Using %s", GetVersion() );
init_locks();
// Tell dso's wxDynamicLibrary destructor not to Unload() the program image,
// since everything is fine before this. In those cases where THROW_IO_ERROR
// is called, dso is destroyed and the DSO/DLL is unloaded before returning in
// those error cases.
(void) dso.Detach();
wxLogDebug( "Using %s", GetVersion() );
s_initialized = true;
}
@ -169,14 +178,11 @@ void KICAD_CURL::Cleanup()
if( s_initialized )
{
curl_global_cleanup();
KICAD_CURL::global_cleanup();
kill_locks();
// dyn_funcs are not good for anything now, assuming process is ending soon here.
for( unsigned i=0; i < DIM(dyn_funcs); ++i )
{
*dyn_funcs[i].address = 0;
}
atexit( &at_terminate );
s_initialized = false;
}
@ -189,7 +195,7 @@ std::string KICAD_CURL::GetSimpleVersion()
if( !s_initialized )
Init();
curl_version_info_data *info = KICAD_CURL::version_info( CURLVERSION_NOW );
curl_version_info_data* info = curl_version_info( CURLVERSION_NOW );
std::string res;

View File

@ -52,29 +52,24 @@ KICAD_CURL_EASY::KICAD_CURL_EASY() :
KICAD_CURL::Init();
// Do not catch exception from KICAD_CURL::Init() at this level.
// Instantiation of this instance will fail if Init() throws, thus ensuring
// that this instance cannot be subsequently used.
// Caller needs a try catch around KICAD_CURL_EASY instantiation.
m_CURL = KICAD_CURL::easy_init();
m_CURL = curl_easy_init();
if( !m_CURL )
{
THROW_IO_ERROR( "Unable to initialize CURL session" );
}
KICAD_CURL::easy_setopt( m_CURL, CURLOPT_WRITEFUNCTION, write_callback );
KICAD_CURL::easy_setopt( m_CURL, CURLOPT_WRITEDATA, (void*) &m_buffer );
curl_easy_setopt( m_CURL, CURLOPT_WRITEFUNCTION, write_callback );
curl_easy_setopt( m_CURL, CURLOPT_WRITEDATA, (void*) &m_buffer );
}
KICAD_CURL_EASY::~KICAD_CURL_EASY()
{
if( m_headers )
KICAD_CURL::slist_free_all( m_headers );
curl_slist_free_all( m_headers );
KICAD_CURL::easy_cleanup( m_CURL );
curl_easy_cleanup( m_CURL );
}
@ -82,13 +77,13 @@ void KICAD_CURL_EASY::Perform()
{
if( m_headers )
{
KICAD_CURL::easy_setopt( m_CURL, CURLOPT_HTTPHEADER, m_headers );
curl_easy_setopt( m_CURL, CURLOPT_HTTPHEADER, m_headers );
}
// bonus: retain worst case memory allocation, should re-use occur
m_buffer.clear();
CURLcode res = KICAD_CURL::easy_perform( m_CURL );
CURLcode res = curl_easy_perform( m_CURL );
if( res != CURLE_OK )
{

View File

@ -30,7 +30,6 @@
* (locale handling)
*/
#include <kicad_curl/kicad_curl.h> /* Include before any wx file */
#include <fctsys.h>
#include <wx/html/htmlwin.h>
#include <wx/fs_zip.h>
@ -48,7 +47,6 @@
#include <id.h>
#include <build_version.h>
#include <hotkeys_basic.h>
#include <online_help.h>
#include <gestfich.h>
#include <menus_helpers.h>
#include <confirm.h>
@ -290,8 +288,6 @@ void PGM_BASE::destroy()
{
// unlike a normal destructor, this is designed to be called more than once safely:
KICAD_CURL::Cleanup();
delete m_common_settings;
m_common_settings = 0;

View File

@ -25,6 +25,7 @@
#include <cstdarg>
#include <config.h> // HAVE_FGETC_NOLOCK
#include <richio.h>

View File

@ -0,0 +1,674 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Chris Pavlina <pavlina.chris@gmail.com>
* Copyright (C) 2016 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 3
* 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 <cctype>
#include <widgets/widget_hotkey_list.h>
#include <wx/dataview.h>
#include <wx/statline.h>
#include <draw_frame.h>
#include <dialog_shim.h>
/**
* Minimum width of the hotkey column
*/
static const int HOTKEY_MIN_WIDTH = 100;
/**
* Extra margin to compensate for vertical scrollbar
*/
static const int HORIZ_MARGIN = 30;
/**
* Menu IDs for the hotkey context menu
*/
enum ID_WHKL_MENU_IDS
{
ID_EDIT = 2001,
ID_RESET,
ID_RESET_ALL,
};
/**
* Class WIDGET_HOTKEY_CLIENT_DATA
* Stores the hotkey and section tag associated with each row. To change a
* hotkey, edit it in the row's client data, then call WIDGET_HOTKEY_LIST::UpdateFromClientData().
*/
class WIDGET_HOTKEY_CLIENT_DATA : public wxClientData
{
EDA_HOTKEY m_hotkey;
wxString m_section_tag;
public:
WIDGET_HOTKEY_CLIENT_DATA( const EDA_HOTKEY& aHotkey, const wxString& aSectionTag )
: m_hotkey( aHotkey ), m_section_tag( aSectionTag )
{}
EDA_HOTKEY& GetHotkey() { return m_hotkey; }
const wxString& GetSectionTag() const { return m_section_tag; }
};
/**
* Class HK_PROMPT_DIALOG
* Dialog to prompt the user to enter a key.
*/
class HK_PROMPT_DIALOG : public DIALOG_SHIM
{
wxKeyEvent m_event;
public:
HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
const wxString& aName, const wxString& aCurrentKey )
: DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
{
wxPanel* panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
/* Dialog layout:
*
* inst_label........................
* ----------------------------------
*
* cmd_label_0 cmd_label_1 \
* | fgsizer
* key_label_0 key_label_1 /
*/
wxStaticText* inst_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL );
inst_label->SetLabelText( _( "Press a new hotkey, or press Esc to cancel..." ) );
sizer->Add( inst_label, 0, wxALL, 5 );
sizer->Add( new wxStaticLine( panel ), 0, wxALL | wxEXPAND, 2 );
wxFlexGridSizer* fgsizer = new wxFlexGridSizer( 2 );
wxStaticText* cmd_label_0 = new wxStaticText( panel, wxID_ANY, _( "Command:" ) );
fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
wxStaticText* cmd_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
cmd_label_1->SetLabel( aName );
fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
wxStaticText* key_label_0 = new wxStaticText( panel, wxID_ANY, _( "Current key:" ) );
fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
wxStaticText* key_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
key_label_1->SetFont( key_label_1->GetFont().Bold() );
key_label_1->SetLabel( aCurrentKey );
fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
sizer->Add( fgsizer, 1, wxEXPAND );
// Wrap the sizer in a second to give a larger border around the whole dialog
wxBoxSizer* outer_sizer = new wxBoxSizer( wxVERTICAL );
outer_sizer->Add( sizer, 0, wxALL | wxEXPAND, 10 );
panel->SetSizer( outer_sizer );
Layout();
outer_sizer->Fit( this );
Center();
SetMinClientSize( GetClientSize() );
// Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events,
// including specials like Tab and Return, are received, particularly
// on MSW.
panel->Bind( wxEVT_CHAR, &HK_PROMPT_DIALOG::OnChar, this );
panel->Bind( wxEVT_CHAR_HOOK, &HK_PROMPT_DIALOG::OnCharHook, this );
}
void OnCharHook( wxKeyEvent& aEvent )
{
// On certain platforms, EVT_CHAR_HOOK is the only handler that receives
// certain "special" keys. However, it doesn't always receive "normal"
// keys correctly. For example, with a US keyboard, it sees ? as shift+/.
//
// Untangling these incorrect keys would be too much trouble, so we bind
// both events, and simply skip the EVT_CHAR_HOOK if it receives a
// "normal" key.
const enum wxKeyCode skipped_keys[] =
{
WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL,
WXK_NUMLOCK, WXK_SCROLL, WXK_RAW_CONTROL
};
int key = aEvent.GetKeyCode();
for( size_t i = 0; i < sizeof( skipped_keys ) / sizeof( skipped_keys[0] ); ++i )
{
if( key == skipped_keys[i] )
return;
}
if( key <= 255 && isprint( key ) && !isspace( key ) )
{
// Let EVT_CHAR handle this one
aEvent.DoAllowNextEvent();
// On Windows, wxEvent::Skip must NOT be called.
// On Linux and OSX, wxEvent::Skip MUST be called.
// No, I don't know why.
#ifndef __WXMSW__
aEvent.Skip();
#endif
}
else
{
OnChar( aEvent );
}
}
void OnChar( wxKeyEvent& aEvent )
{
m_event = aEvent;
EndFlexible( wxID_OK );
}
/**
* End the dialog whether modal or quasimodal
*/
void EndFlexible( int aRtnCode )
{
if( IsQuasiModal() )
EndQuasiModal( aRtnCode );
else
EndModal( aRtnCode );
}
static wxKeyEvent PromptForKey( wxWindow* aParent, const wxString& aName,
const wxString& aCurrentKey )
{
HK_PROMPT_DIALOG dialog( aParent, wxID_ANY, _( "Set Hotkey" ), aName, aCurrentKey );
if( dialog.ShowModal() == wxID_OK )
{
return dialog.m_event;
}
else
{
wxKeyEvent dummy;
return dummy;
}
}
};
WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::GetHKClientData( wxTreeListItem aItem )
{
if( aItem.IsOk() )
{
wxClientData* data = GetItemData( aItem );
if( !data )
{
return NULL;
}
else
{
return static_cast<WIDGET_HOTKEY_CLIENT_DATA*>( data );
}
}
else
{
return NULL;
}
}
WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::GetSelHKClientData()
{
return GetHKClientData( GetSelection() );
}
void WIDGET_HOTKEY_LIST::UpdateFromClientData()
{
for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i );
if( hkdata )
{
EDA_HOTKEY& hk = hkdata->GetHotkey();
SetItemText( i, 0, wxGetTranslation( hk.m_InfoMsg ) );
SetItemText( i, 1, KeyNameFromKeyCode( hk.m_KeyCode ) );
}
}
}
void WIDGET_HOTKEY_LIST::LoadSection( EDA_HOTKEY_CONFIG* aSection )
{
HOTKEY_LIST list;
for( EDA_HOTKEY** info_ptr = aSection->m_HK_InfoList; *info_ptr; ++info_ptr )
{
list.push_back( **info_ptr );
}
m_hotkeys.push_back( list );
}
void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
if( !hkdata )
{
// Activated item was not a hotkey row
return;
}
wxString name = GetItemText( aItem, 0 );
wxString current_key = GetItemText( aItem, 1 );
wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
long key = MapKeypressToKeycode( key_event );
if( hkdata && key )
{
// See if this key code is handled in hotkeys names list
bool exists;
KeyNameFromKeyCode( key, &exists );
if( exists && hkdata->GetHotkey().m_KeyCode != key )
{
wxString tag = hkdata->GetSectionTag();
bool canUpdate = ResolveKeyConflicts( key, tag );
if( canUpdate )
{
hkdata->GetHotkey().m_KeyCode = key;
}
}
UpdateFromClientData();
}
}
void WIDGET_HOTKEY_LIST::ResetItem( wxTreeListItem aItem )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
EDA_HOTKEY* hk = &hkdata->GetHotkey();
for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
{
wxString& section_tag = *( m_sections[sec_index].m_section->m_SectionTag );
if( section_tag != hkdata->GetSectionTag() )
continue;
HOTKEY_LIST& each_list = m_hotkeys[sec_index];
HOTKEY_LIST::iterator hk_it;
for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it )
{
if( hk_it->m_Idcommand == hk->m_Idcommand )
{
hk->m_KeyCode = hk_it->m_KeyCode;
break;
}
}
}
UpdateFromClientData();
}
void WIDGET_HOTKEY_LIST::OnActivated( wxTreeListEvent& aEvent )
{
EditItem( aEvent.GetItem() );
}
void WIDGET_HOTKEY_LIST::OnContextMenu( wxTreeListEvent& aEvent )
{
// Save the active event for use in OnMenu
m_context_menu_item = aEvent.GetItem();
wxMenu menu;
menu.Append( ID_EDIT, _( "Edit..." ) );
menu.Append( ID_RESET, _( "Reset" ) );
menu.Append( wxID_SEPARATOR );
menu.Append( ID_RESET_ALL, _( "Reset all" ) );
PopupMenu( &menu );
}
void WIDGET_HOTKEY_LIST::OnMenu( wxCommandEvent& aEvent )
{
switch( aEvent.GetId() )
{
case ID_EDIT:
EditItem( m_context_menu_item );
break;
case ID_RESET:
ResetItem( m_context_menu_item );
break;
case ID_RESET_ALL:
TransferDataToControl();
break;
default:
wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
}
}
void WIDGET_HOTKEY_LIST::OnSize( wxSizeEvent& aEvent )
{
// Handle this manually - wxTreeListCtrl screws up the width of the first column
wxDataViewCtrl* view = GetDataView();
if( !view )
return;
wxRect rect = GetClientRect();
view->SetSize( rect );
#ifdef wxHAS_GENERIC_DATAVIEWCTRL
{
wxWindow* view = GetView();
view->Refresh();
view->Update();
}
#endif
// Find the maximum width of the hotkey column
int hk_column_width = 0;
for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
{
const wxString& text = GetItemText( item, 1 );
int width = WidthFor( text );
if( width > hk_column_width )
hk_column_width = width;
}
if( hk_column_width < HOTKEY_MIN_WIDTH )
hk_column_width = HOTKEY_MIN_WIDTH;
SetColumnWidth( 1, hk_column_width );
SetColumnWidth( 0, rect.width - hk_column_width - HORIZ_MARGIN );
}
bool WIDGET_HOTKEY_LIST::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect )
{
EDA_HOTKEY* conflicting_key = NULL;
struct EDA_HOTKEY_CONFIG* conflicting_section = NULL;
for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
if( !hkdata )
continue;
EDA_HOTKEY& hk = hkdata->GetHotkey();
wxString tag = hkdata->GetSectionTag();
if( aSectionTag != g_CommonSectionTag
&& tag != g_CommonSectionTag
&& tag != aSectionTag )
{
// This key and its conflict candidate are in orthogonal sections, so skip.
continue;
}
if( aKey == hk.m_KeyCode )
{
conflicting_key = &hk;
// Find the section
HOTKEY_SECTIONS::iterator it;
for( it = m_sections.begin(); it != m_sections.end(); ++it )
{
if( *it->m_section->m_SectionTag == tag )
{
conflicting_section = it->m_section;
break;
}
}
}
}
// Write the outparams
if( aConfKey )
*aConfKey = conflicting_key;
if( aConfSect )
*aConfSect = conflicting_section;
return conflicting_key == NULL;
}
bool WIDGET_HOTKEY_LIST::ResolveKeyConflicts( long aKey, const wxString& aSectionTag )
{
EDA_HOTKEY* conflicting_key = NULL;
EDA_HOTKEY_CONFIG* conflicting_section = NULL;
CheckKeyConflicts( aKey, aSectionTag, &conflicting_key, &conflicting_section );
if( conflicting_key != NULL )
{
wxString info = wxGetTranslation( conflicting_key->m_InfoMsg );
wxString msg = wxString::Format(
_( "<%s> is already assigned to \"%s\" in section \"%s\". Are you sure you want "
"to change its assignment?" ),
KeyNameFromKeyCode( aKey ), GetChars( info ),
*(conflicting_section->m_Title) );
wxMessageDialog dlg( GetParent(), msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT );
if( dlg.ShowModal() == wxID_YES )
{
conflicting_key->m_KeyCode = 0;
UpdateFromClientData();
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, const HOTKEY_SECTIONS& aSections )
: wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
m_sections( aSections )
{
AppendColumn( _( "Command" ) );
AppendColumn( _( "Hotkey" ) );
Bind( wxEVT_TREELIST_ITEM_ACTIVATED, &WIDGET_HOTKEY_LIST::OnActivated, this );
Bind( wxEVT_TREELIST_ITEM_CONTEXT_MENU, &WIDGET_HOTKEY_LIST::OnContextMenu, this );
Bind( wxEVT_MENU, &WIDGET_HOTKEY_LIST::OnMenu, this );
Bind( wxEVT_SIZE, &WIDGET_HOTKEY_LIST::OnSize, this );
}
HOTKEY_SECTIONS WIDGET_HOTKEY_LIST::GenSections( EDA_HOTKEY_CONFIG* aHotkeys )
{
HOTKEY_SECTIONS sections;
for( EDA_HOTKEY_CONFIG* section = aHotkeys; section->m_HK_InfoList; ++section )
{
HOTKEY_SECTION sec;
sec.m_name = wxGetTranslation( *section->m_Title );
sec.m_section = section;
sections.push_back( sec );
}
return sections;
}
void WIDGET_HOTKEY_LIST::InstallOnPanel( wxPanel* aPanel )
{
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
sizer->Add( this, 1, wxALL | wxEXPAND, 0 );
aPanel->SetSizer( sizer );
}
bool WIDGET_HOTKEY_LIST::TransferDataToControl()
{
Freeze();
DeleteAllItems();
m_hotkeys.clear();
for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
{
// LoadSection pushes into m_hotkeys
LoadSection( m_sections[sec_index].m_section );
wxASSERT( m_hotkeys.size() == sec_index + 1 );
wxString section_tag = *( m_sections[sec_index].m_section->m_SectionTag );
// Create parent tree item
wxTreeListItem parent = AppendItem( GetRootItem(), m_sections[sec_index].m_name );
HOTKEY_LIST& each_list = m_hotkeys[sec_index];
HOTKEY_LIST::iterator hk_it;
for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it )
{
wxTreeListItem item = AppendItem( parent, wxEmptyString );
SetItemData( item, new WIDGET_HOTKEY_CLIENT_DATA( &*hk_it, section_tag ) );
}
Expand( parent );
}
UpdateFromClientData();
Thaw();
return true;
}
bool WIDGET_HOTKEY_LIST::TransferDataFromControl()
{
for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
{
EDA_HOTKEY_CONFIG* section = m_sections[sec_index].m_section;
for( EDA_HOTKEY** info_ptr = section->m_HK_InfoList; *info_ptr; ++info_ptr )
{
EDA_HOTKEY* info = *info_ptr;
for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
if( !hkdata )
continue;
EDA_HOTKEY& hk = hkdata->GetHotkey();
if( hk.m_Idcommand == info->m_Idcommand )
{
info->m_KeyCode = hk.m_KeyCode;
break;
}
}
}
}
return true;
}
long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
{
long key = aEvent.GetKeyCode();
if( key == WXK_ESCAPE )
{
return 0;
}
else
{
if( key >= 'a' && key <= 'z' ) // convert to uppercase
key = key + ('A' - 'a');
// Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL)
// to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z'
if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
key += 'A' - 1;
/* Disallow shift for keys that have two keycodes on them (e.g. number and
* punctuation keys) leaving only the "letter keys" of A-Z.
* Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
* and Ctrl-( and Ctrl-5 (FR layout).
* Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
*/
bool keyIsLetter = key >= 'A' && key <= 'Z';
if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) )
key |= GR_KB_SHIFT;
if( aEvent.ControlDown() )
key |= GR_KB_CTRL;
if( aEvent.AltDown() )
key |= GR_KB_ALT;
return key;
}
}

View File

@ -132,6 +132,7 @@ set( EESCHEMA_SRCS
onrightclick.cpp
operations_on_items_lists.cpp
pinedit.cpp
pin_number.cpp
plot_schematic_DXF.cpp
plot_schematic_HPGL.cpp
plot_schematic_PS.cpp

View File

@ -33,9 +33,9 @@
#include <confirm.h>
#include <schframe.h>
#include <sch_reference_list.h>
#include <class_library.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly )
@ -111,11 +111,11 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
// Build component list
if( aAnnotateSchematic )
{
sheets.GetComponents( Prj().SchLibs(), references );
g_RootSheet->GetComponents( Prj().SchLibs(), references );
}
else
{
m_CurrentSheet->GetComponents( Prj().SchLibs(), references );
m_CurrentSheet->Last()->GetComponents( Prj().SchLibs(), references, true, false );
}
// Break full components reference in name (prefix) and number:
@ -186,14 +186,13 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOnly )
{
// build the screen list
SCH_SHEET_LIST SheetList;
SCH_REFERENCE_LIST ComponentsList;
// Build the list of components
if( !aOneSheetOnly )
SheetList.GetComponents( Prj().SchLibs(), ComponentsList );
g_RootSheet->GetComponents( Prj().SchLibs(), ComponentsList );
else
m_CurrentSheet->GetComponents( Prj().SchLibs(), ComponentsList );
m_CurrentSheet->Last()->GetComponents( Prj().SchLibs(), ComponentsList, true, false );
return ComponentsList.CheckAnnotation( aMessageList );
}

View File

@ -38,9 +38,10 @@
#include <wildcards_and_files_ext.h>
#include <general.h>
#include <sch_sheet_path.h>
#include <sch_sheet.h>
#include <sch_component.h>
#include <sch_reference_list.h>
#include <sch_sheet_path.h>
#include <dsnlexer.h>
#include <ptree.h>
@ -53,10 +54,9 @@ void SCH_EDIT_FRAME::backAnnotateFootprints( const std::string& aChangedSetOfRef
{
// Build a flat list of components in schematic:
SCH_REFERENCE_LIST refs;
SCH_SHEET_LIST sheets;
bool isChanged = false;
sheets.GetComponents( Prj().SchLibs(), refs, false );
g_RootSheet->GetComponents( Prj().SchLibs(), refs, false );
DSNLEXER lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
PTREE doc;
@ -135,9 +135,8 @@ bool SCH_EDIT_FRAME::ProcessCmpToFootprintLinkFile( const wxString& aFullFilenam
{
// Build a flat list of components in schematic:
SCH_REFERENCE_LIST referencesList;
SCH_SHEET_LIST sheetList;
sheetList.GetComponents( Prj().SchLibs(), referencesList, false );
g_RootSheet->GetComponents( Prj().SchLibs(), referencesList, false );
FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );

View File

@ -36,8 +36,9 @@
#include <fctsys.h>
#include <kicad_string.h>
#include <schframe.h>
#include <sch_reference_list.h>
#include <sch_component.h>
#include <sch_sheet.h>
#include <sch_reference_list.h>
#include <boost/foreach.hpp>
@ -69,6 +70,7 @@ bool SCH_REFERENCE_LIST::sortByXPosition( const SCH_REFERENCE& item1,
return ii < 0;
}
bool SCH_REFERENCE_LIST::sortByYPosition( const SCH_REFERENCE& item1,
const SCH_REFERENCE& item2 )
{
@ -132,7 +134,9 @@ bool SCH_REFERENCE_LIST::sortByReferenceOnly( const SCH_REFERENCE& item1,
bool SCH_REFERENCE_LIST::sortByTimeStamp( const SCH_REFERENCE& item1,
const SCH_REFERENCE& item2 )
{
int ii = item1.m_SheetPath.Cmp( item2.m_SheetPath );
wxCHECK( item1.m_Sheet != NULL && item2.m_Sheet != NULL, false );
int ii = *item1.m_Sheet - *item2.m_Sheet;
if( ii == 0 )
ii = item1.m_TimeStamp - item2.m_TimeStamp;
@ -140,6 +144,7 @@ bool SCH_REFERENCE_LIST::sortByTimeStamp( const SCH_REFERENCE& item1,
return ii < 0;
}
int SCH_REFERENCE_LIST::FindUnit( size_t aIndex, int aUnit )
{
int NumRef;
@ -286,7 +291,7 @@ int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector<int>& aIdList, int aFi
void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
SCH_MULTI_UNIT_REFERENCE_MAP& aLockedUnitMap )
{
if ( componentFlatList.size() == 0 )
return;
@ -332,9 +337,11 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
// Check whether this component is in aLockedUnitMap.
SCH_REFERENCE_LIST* lockedList = NULL;
BOOST_FOREACH( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair, aLockedUnitMap )
{
unsigned n_refs = pair.second.GetCount();
for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
{
SCH_REFERENCE &thisRef = pair.second[thisRefI];
@ -414,22 +421,29 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
if( lockedList != NULL )
{
unsigned n_refs = lockedList->GetCount();
for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
{
SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
if( thisRef.IsSameInstance( componentFlatList[ii] ) )
{
// This is the component we're currently annotating. Hold the unit!
componentFlatList[ii].m_Unit = thisRef.m_Unit;
}
if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue;
if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue;
if( thisRef.CompareValue( componentFlatList[ii] ) != 0 )
continue;
if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 )
continue;
// Find the matching component
for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
{
if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue;
if( ! thisRef.IsSameInstance( componentFlatList[jj] ) )
continue;
componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
componentFlatList[jj].m_Unit = thisRef.m_Unit;
componentFlatList[jj].m_IsNew = false;
@ -438,13 +452,12 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
}
}
}
else
{
/* search for others units of this component.
* we search for others parts that have the same value and the same
* reference prefix (ref without ref number)
*/
* we search for others parts that have the same value and the same
* reference prefix (ref without ref number)
*/
for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
{
if( componentFlatList[ii].m_Unit == Unit )
@ -498,7 +511,7 @@ int SCH_REFERENCE_LIST::CheckAnnotation( wxArrayString* aMessageList )
SortByRefAndValue();
// Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1.
// Split reference designators into name (prefix) and number: IC1 becomes IC, and 1.
SplitReferences();
// count not yet annotated items or annotation error.
@ -668,14 +681,14 @@ int SCH_REFERENCE_LIST::CheckAnnotation( wxArrayString* aMessageList )
for( int ii = 0; ( ii < imax ) && ( error < 4 ); ii++ )
{
if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
|| ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() ) )
|| ( componentFlatList[ii].GetSheet() != componentFlatList[ii + 1].GetSheet() ) )
continue;
// Same time stamp found.
wxString full_path;
full_path.Printf( wxT( "%s%8.8X" ),
GetChars( componentFlatList[ii].GetSheetPath().Path() ),
GetChars( componentFlatList[ii].GetSheet()->GetPath() ),
componentFlatList[ii].m_TimeStamp );
msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ),
@ -695,24 +708,24 @@ int SCH_REFERENCE_LIST::CheckAnnotation( wxArrayString* aMessageList )
SCH_REFERENCE::SCH_REFERENCE( SCH_COMPONENT* aComponent, LIB_PART* aLibComponent,
SCH_SHEET_PATH& aSheetPath )
SCH_SHEET* aSheet )
{
wxASSERT( aComponent != NULL && aLibComponent != NULL );
m_RootCmp = aComponent;
m_Entry = aLibComponent;
m_Unit = aComponent->GetUnitSelection( aSheetPath.Last() );
m_SheetPath = aSheetPath;
m_Unit = aComponent->GetUnitSelection( aSheet );
m_Sheet = aSheet;
m_IsNew = false;
m_Flag = 0;
m_TimeStamp = aComponent->GetTimeStamp();
m_CmpPos = aComponent->GetPosition();
m_SheetNum = 0;
if( aComponent->GetRef( aSheetPath.Last() ).IsEmpty() )
aComponent->SetRef( aSheetPath.Last(), wxT( "DefRef?" ) );
if( aComponent->GetRef( aSheet ).IsEmpty() )
aComponent->SetRef( aSheet, wxT( "DefRef?" ) );
SetRef( aComponent->GetRef( aSheetPath.Last() ) );
SetRef( aComponent->GetRef( aSheet ) );
m_NumRef = -1;
@ -730,9 +743,9 @@ void SCH_REFERENCE::Annotate()
else
m_Ref = TO_UTF8( GetRef() << m_NumRef );
m_RootCmp->SetRef( m_SheetPath.Last(), FROM_UTF8( m_Ref.c_str() ) );
m_RootCmp->SetRef( m_Sheet, FROM_UTF8( m_Ref.c_str() ) );
m_RootCmp->SetUnit( m_Unit );
m_RootCmp->SetUnitSelection( &m_SheetPath, m_Unit );
m_RootCmp->SetUnitSelection( m_Sheet, m_Unit );
}
@ -766,7 +779,7 @@ void SCH_REFERENCE::Split()
{
while( ll >= 0 )
{
if( (refText[ll] <= ' ' ) || isdigit( refText[ll] ) )
if( ( refText[ll] <= ' ' ) || isdigit( refText[ll] ) )
ll--;
else
{

View File

@ -340,7 +340,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions()
{
int unit_selection = unitChoice->GetCurrentSelection() + 1;
m_cmp->SetUnitSelection( &m_parent->GetCurrentSheet(), unit_selection );
m_cmp->SetUnitSelection( m_parent->GetCurrentSheet().Last(), unit_selection );
m_cmp->SetUnit( unit_selection );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 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
@ -30,10 +30,14 @@
#include <class_base_screen.h>
#include <dialog_eeschema_options.h>
#include <widgets/widget_hotkey_list.h>
#include <schframe.h>
#include <hotkeys.h>
#include "wx/settings.h"
#include <wx/settings.h>
DIALOG_EESCHEMA_OPTIONS::DIALOG_EESCHEMA_OPTIONS( wxWindow* parent ) :
DIALOG_EESCHEMA_OPTIONS::DIALOG_EESCHEMA_OPTIONS( SCH_EDIT_FRAME* parent ) :
DIALOG_EESCHEMA_OPTIONS_BASE( parent )
{
m_choiceUnits->SetFocus();
@ -50,9 +54,29 @@ DIALOG_EESCHEMA_OPTIONS::DIALOG_EESCHEMA_OPTIONS( wxWindow* parent ) :
m_fieldGrid->AutoSizeColLabelSize( i );
}
// Embed the hotkeys list
HOTKEY_SECTIONS sections = WIDGET_HOTKEY_LIST::GenSections( g_Eeschema_Hokeys_Descr );
m_hotkeyListCtrl = new WIDGET_HOTKEY_LIST( m_panelHotkeys, sections );
m_hotkeyListCtrl->InstallOnPanel( m_panelHotkeys );
// Make sure we select the first tab of the options tab page
m_notebook->SetSelection( 0 );
// Lay out all child pages
// No, I don't know why this->Layout() doesn't propagate through to these,
// but at least on MSW, it does not.
for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
{
m_notebook->GetPage( i )->Layout();
}
Layout();
}
SCH_EDIT_FRAME* DIALOG_EESCHEMA_OPTIONS::GetParent()
{
return static_cast<SCH_EDIT_FRAME*>( DIALOG_EESCHEMA_OPTIONS_BASE::GetParent() );
}
@ -147,11 +171,13 @@ void DIALOG_EESCHEMA_OPTIONS::OnAddButtonClick( wxCommandEvent& event )
for( int row = 0; row < m_fieldGrid->GetNumberRows(); ++row )
{
bool this_row_selected = false;
for( int col = 0; col < m_fieldGrid->GetNumberCols(); ++col )
{
if( m_fieldGrid->IsInSelection( row, col ) )
this_row_selected = true;
}
if( this_row_selected )
{
selected_row = row;
@ -198,10 +224,12 @@ void DIALOG_EESCHEMA_OPTIONS::OnDeleteButtonClick( wxCommandEvent& event )
TransferDataFromWindow();
int n_rows = m_fieldGrid->GetNumberRows();
for( int count = 0; count < n_rows; ++count )
{
// Iterate backwards, unsigned-friendly way for future
int row = n_rows - count - 1;
if( rows_to_delete[row] )
{
templateFields.erase( templateFields.begin() + row );
@ -217,9 +245,14 @@ bool DIALOG_EESCHEMA_OPTIONS::TransferDataToWindow()
if( !wxDialog::TransferDataToWindow() )
return false;
if( !m_hotkeyListCtrl->TransferDataToControl() )
return false;
m_fieldGrid->Freeze();
if( m_fieldGrid->GetNumberRows() )
m_fieldGrid->DeleteRows( 0, m_fieldGrid->GetNumberRows() );
m_fieldGrid->AppendRows( templateFields.size() );
for( int row = 0; row < m_fieldGrid->GetNumberRows(); ++row )
@ -238,21 +271,34 @@ bool DIALOG_EESCHEMA_OPTIONS::TransferDataToWindow()
m_fieldGrid->SetCellRenderer( row, 2, new wxGridCellBoolRenderer() );
m_fieldGrid->SetCellAlignment( row, 2, wxALIGN_CENTRE, wxALIGN_CENTRE );
}
m_fieldGrid->AutoSizeRows();
m_fieldGrid->Thaw();
Layout();
return true;
}
bool DIALOG_EESCHEMA_OPTIONS::TransferDataFromWindow()
{
if( !wxDialog::TransferDataFromWindow() )
return false;
if( !m_hotkeyListCtrl->TransferDataFromControl() )
return false;
// Refresh hotkeys
GetParent()->ReCreateMenuBar();
GetParent()->Refresh();
for( int row = 0; row < m_fieldGrid->GetNumberRows(); ++row )
{
templateFields[row].m_Name = m_fieldGrid->GetCellValue( row, 0 );
templateFields[row].m_Name = m_fieldGrid->GetCellValue( row, 0 );
templateFields[row].m_Value = m_fieldGrid->GetCellValue( row, 1 );
templateFields[row].m_Visible = ( m_fieldGrid->GetCellValue( row, 2 ) != wxEmptyString );
}
return true;
}
@ -271,4 +317,3 @@ TEMPLATE_FIELDNAMES DIALOG_EESCHEMA_OPTIONS::GetTemplateFields( void )
{
return templateFields;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 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
@ -34,9 +34,14 @@
#include <dialog_eeschema_options_base.h>
#include <template_fieldnames.h>
class WIDGET_HOTKEY_LIST;
class SCH_EDIT_FRAME;
class DIALOG_EESCHEMA_OPTIONS : public DIALOG_EESCHEMA_OPTIONS_BASE
{
protected:
WIDGET_HOTKEY_LIST* m_hotkeyListCtrl;
/** @brief The template fieldnames for this dialog */
TEMPLATE_FIELDNAMES templateFields;
@ -80,7 +85,9 @@ public:
*
* @param parent The dialog's parent
*/
DIALOG_EESCHEMA_OPTIONS( wxWindow* parent );
DIALOG_EESCHEMA_OPTIONS( SCH_EDIT_FRAME* parent );
virtual SCH_EDIT_FRAME* GetParent();
/**
* Function GetUnitsSelection

Some files were not shown because too many files have changed in this diff Show More