Commit 0bebc34a authored by Garth Corral's avatar Garth Corral

Merge trunk @ 5376

parents 267bca58 77fb1897
......@@ -54,15 +54,15 @@ if( Bazaar_EXECUTABLE )
# Fetch the Bazaar executable version.
execute_process( COMMAND ${Bazaar_EXECUTABLE} --version
OUTPUT_VARIABLE bzr_version_output
OUTPUT_VARIABLE _bzr_version_output
ERROR_VARIABLE _bzr_version_error
RESULT_VARIABLE _bzr_version_result
OUTPUT_STRIP_TRAILING_WHITESPACE )
if( ${_bzr_version_result} EQUAL 0 )
set( Bazaar_FOUND TRUE )
string( REGEX REPLACE "^(.*\n)? \(bzr\) ([^\n]+).*"
"\\2" Bazaar_VERSION "${_bzr_version_output}" )
string( REGEX REPLACE "^[\n]*Bazaar \\(bzr\\) ([0-9.a-z]+).*"
"\\1" Bazaar_VERSION "${_bzr_version_output}" )
message( STATUS "Bazaar version control system version ${Bazaar_VERSION} found." )
endif( ${_bzr_version_result} EQUAL 0 )
......
......@@ -646,7 +646,8 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = stable-release-policy.md \
INPUT = coding-style-policy.md \
stable-release-policy.md \
road-map.md
# This tag can be used to specify the character encoding of the source files
......
# KiCad C++ Source Code Style Guide #
Latest Publishing: February 2013
First Published: September 2010
written by
Wayne Stambaugh \<<stambaughw@verizon.net>\>
and
Dick Hollenbeck \<<dick@softplc.com>\>
[TOC]
# 1. Introduction # {#intro}
The purpose of this document is to provide a reference guide for KiCad
developers about how source code should be styled and formatted in
KiCad. It is not a comprehensive programming guide because it does not
discuss many things such as software engineering strategies, source
directories, existing classes, or how to internationalize text. The goal
is to make all of the KiCad source conform to this guide.
## 1.1 Why Coding Style Matters ## {#why}
You may be thinking to yourself that using the style defined in this
document will not make you a good programmer and you would be correct.
Any given coding style is no substitute for experience. However, any
experienced coder will tell that the only thing worse than looking at
code that is not in your preferred coding style, is looking at twenty
different coding styles that are not your preferred coding style.
Consistency makes a) problems easier to spot, and b) looking at code for
long periods of time more tolerable.
## 1.2 Enforcement ## {#enforcement}
The KiCad coding police are not going to break down your door and beat
you with your keyboard if you don't follow these guidelines (although
there are those who would argue that they should). However, there are
some very sound reasons why you should follow them. If you are
contributing patches, you are much more likely to be taken seriously by
the primary developers if your patches are formatted correctly. Busy
developers don't have the time to go back and reformat your code. If you
have a desire to become a regular KiCad developer with commit access to
the development branch, you're not likely to get a glowing
recommendation by the lead developers if you will not follow these
guidelines. It is just good programming courtesy to follow this policy
because it is respectful of the investment already made by the existing
developers. The other KiCad developers will appreciate your effort.
**Warning**
**Do not modify this document without the consent of the project
leader. All changes to this document require approval.**
# 2. Naming Conventions # {#naming_conventions}
Before delving into anything as esoteric as indentation and formatting,
naming conventions need to be addressed. This section does not attempt
to define what names you use for your code. Rather, it defines the style
for naming. See the references section for links to some excellent
coding references. When defining multiple word names use the following
conventions for improved readability:
- Use underscores for all upper and all lower case variables to make
multiple word names more readable.
- Use camel case for mixed case variable names.
Avoid mixing camel case and underscores.
**Examples**
~~~~~~~~~~~~~{.cpp}
CamelCaseName // if camelcase, then no underscores
all_lower_case_name
ALL_UPPER_CASE_NAME
~~~~~~~~~~~~~
## 2.1 Class, Type Definitions, Name Space, and Macro Names ## {#definitions}
Class, typedef, enum, name space, and macro names should be comprised of
all capital letters.
**Examples**
~~~~~~~~~~~~~{.cpp}
class SIMPLE
#define LONG_MACRO_WITH_UNDERSCORES
typedef boost::ptr_vector<PIN> PIN_LIST;
enum KICAD_T {...};
~~~~~~~~~~~~~
## 2.2 Local, Private and Automatic Variables ## {#local_variables}
The first character of automatic, static local, and private variable
names should be lower case. This indicates that the variable will not be
“visible” outside of the function, file, or class where they are
defined, respectively. The limited visibility is being acknowledged with
the lowercase starting letter, where lowercase is considered to be less
boisterous than uppercase.
**Examples**
~~~~~~~~~~~~~{.cpp}
int i;
double aPrivateVariable;
static char* static_variable = NULL;
~~~~~~~~~~~~~
## 2.3 Public and Global Variables ## {#global_variables}
The first character of public and global variable names are to be
uppercase. This indicates that the variable is visible outside the class
or file in which it was defined. (An exception is the use of prefix `g_`
which is also sometimes used to indicate a global variable.)
**Example**
~~~~~~~~~~~~~{.cpp}
char* GlobalVariable;
~~~~~~~~~~~~~
## 2.4 Local, Private and Static Functions ## {#functions}
The first character of local, private, and static functions should be
lower case. This indicates that the function is not visible outside the
class or file where it is defined.
**Example**
~~~~~~~~~~~~~{.cpp}
bool isModified();
static int buildList( int* list );
~~~~~~~~~~~~~
## 2.5 Function Arguments ## {#function_arguments}
Function arguments are prefixed with an 'a' to indicate these are
arguments to a function. The 'a' stands for “argument”, and it also
enables clever and concise Doxygen comments.
**Example**
~~~~~~~~~~~~~{.cpp}
/*/** */*
* Function SetFoo
* takes aFoo and copies it into this instance.
*/
void SetFoo( int aFoo );
~~~~~~~~~~~~~
Notice how the reader can say “a Foo” to himself when reading this.
## 2.6 Pointers ## {#pointers}
It is not desired to identify a pointer by building a 'p' into the
variable name. The pointer aspect of the variable pertains to type, not
purpose.
**Example**
~~~~~~~~~~~~~{.cpp}
MODULE* module;
~~~~~~~~~~~~~
The purpose of the variable is that it represents a MODULE. Something
like `p_module` would only make that harder to discern.
## 2.7 Accessing Member Variables and Member Functions ## {#accessing_members}
We do not use “`this->`” to access either member variables or member
functions from within the containing class. We let C++ perform this for
us.
# 3. Commenting # {#commenting}
Comments in KiCad typically fall into two categories: in line code
comments and Doxygen comments. In line comments have no set formatting
rules other than they should have the same indent level as the code if
they do not follow a statement. In line comments that follow statements
should not exceed 99 columns unless absolutely necessary. The prevents
word wrapping in an editor when the viewable columns is set to 100. In
line comments can use either the C++ or the C commenting style, but C++
comments are preferred for single line comments or comments consisting
of only a few lines.
## 3.1 Blank Lines Above Comments ## {#blank_lines_above_comments}
If a comment is the first thing on a line, then that comment should have
one or more blank lines above them. One blank line is preferred.
## 3.2 Doxygen ## {#doxygen}
Doxygen is a C++ source code documenting tool used by the project. Descriptive
*.html files can be generated from the source code by installing Doxygen and
building the target named **doxygen-docs**.
$ cd <kicad_build_base>
$ make doxygen-docs
The \*.html files will be placed into
\<kicad\_project\_base\>/Documentation/doxygen/html/
Doxygen comments are used to build developer documentation from the
source code. They should normally be only placed in header files and not
in \*.cpp files. This eliminates the obligation to keep two comments in
agreement with each other. is if the class, function, or enum, etc. is
only defined in a \*.cpp source file and not present in any header file,
in which case the Doxygen comments should go into the \*.cpp source file.
Again, avoid duplicating the Doxygen comments in both the header and
\*.cpp source files.
KiCad uses the JAVADOC comment style defined in the [“Documenting the
code”][doccode] section of the Doxygen [manual][manual]. Don't forget
to use the special Doxygen tags: bug, todo, deprecated, etc., so other
developers can quickly get useful information about your code. It is
good practice to actually generate the Doxygen \*.html files by
building target doxygen-docs, and then to review the quality of your
Doxygen comments with a web browser before submitting a patch.
[doccode]: http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
[manual]: http://www.stack.nl/~dimitri/doxygen/manual.html
### 3.2.1 Function Comments ### {#function_comments}
These go into a header file, unless the function is a private (i.e.
static) function known only to a \*.cpp file. The format of a function
comment is chosen to serve a dual purpose role: delineation of the
function declaration within the source code and to create a consistent
leading sentence in the doxygen html output. The chosen format is
“Function \<name\>” as shown in the example below.
**Example**
~~~~~~~~~~~~~{.cpp}
/*/** */*
* Function Print
* formats and writes text to the output stream.
* @param nestLevel is the multiple of spaces to precede the output with.
* @param fmt is a printf() style format string.
* @param ... is a variable list of parameters that will get blended into
* the output under control of the format string.
* @return int - the number of characters output.
* @throw IO_ERROR, if there is a problem outputting, such asisk.
*/
int PRINTF_FUNC Print( int nestLevel,
const char* fmt, ... ) throw( IO_ERROR );
~~~~~~~~~~~~~
The “Function \<name\>” text goes on the 2nd line of the comment. The
\@return keyword if present, should show the type of the return value
followed by a hiphen. The \@param keyword names a function parameter
and the text following should flow like a normal English sentence.
### 3.2.2 Class Comments ### {#class_comments}
A class comment describes a class declaration by giving the purpose and
use of the class. Its format is similar to a function comment. Doxygen
can use the html \<p\> (paragraph designation) to begin a new paragraph
in its output. So if the text of the comment is large, break it put into
multiple paragraphs.
**Example**
~~~~~~~~~~~~~{.cpp}
/*/** */*
* Class OUTPUTFORMATTER
* is an important interface (abstract) class used to output UTF8 text in
* a convenient way. The primary interface is "printf() - like" but
* with support for indentation control. The destination of the 8 bit
* wide text is up to the implementer.
* <p>
* The implementer only has to implement the write() function, but can
* also optionally re-implement GetQuoteChar().
* <p>
* If you want to output a wxString, then use CONV_TO_UTF8() on it
* before passing it as an argument to Print().
* <p>
* Since this is an abstract interface, only classes derived from
* this one may actually be used.
*/
class OUTPUTFORMATTER
{
~~~~~~~~~~~~~
# 4. Formatting # {#formatting}
This section defines the formatting style used in the KiCad source.
## 4.1 Indentation ## {#indentation}
The indentation level for the KiCad source code is defined as four
spaces. Please do not use tabs.
### 4.1.1 Defines ### {#defines}
There should be only one space after a \#define statement.
### 4.1.2 Column Alignment ### {#column_alignment}
Please try to align multiple consecutive similar lines into consistent
columns when possible, such as \#define lines which can be thought of as
containing 4 columns: \#define, symbol, value, and comment. Notice how
all 4 columns are aligned in the example below.
**Example**
~~~~~~~~~~~~~{.cpp}
#define LN_RED 12 // my favorite
#define LN_GREEN 13 // eco friendly
~~~~~~~~~~~~~
Another common case is the declaration of automatic variables. These are
preferably shown in columns of type and variable name.
## 4.2 Blank Lines ## {#blank_lines}
### 4.2.1 Function Declarations ### {#function_declarations}
There should be 1 blank line above a function declaration in a class
file if that function declaration is presented with a Javadoc comment.
This is consist with the statement above about blank lines above
comments.
### 4.2.2 Function Definitions ### {#function_definitions}
Function definitions in *.cpp files will not typically be accompanied by
any comment, since those are normally only in the header file. It is
desirable to set off the function definition within the *.cpp file by
leaving two blank lines above the function definition.
### 4.2.3 If Statements ### {#if_statements}
There should be one blank line above if statements.
## 4.3 Line Length ### {#line_length}
The maximum line width is 99 columns. An exception to this is a long
quoted string such as the internationalized text required to satisfy
MSVC++, described below.
## 4.4 Strings ## {#strings}
The KiCad project team no longer supports compiling with Microsoft
Visual C++. When you need to break long strings into smaller substrings,
please use the C99 compliant method for improved readability. Using
any of previously accepted methods defined below for breaking
long internationalized strings will no longer be accepted.
**Examples**
~~~~~~~~~~~~~{.cpp}
// This works with C99 compliant compilers is the **only** accepted method:
wxChar* foo = _( “this is a long string broken ”
“into pieces for readability.” );
// This works with MSVC, breaks POEdit, and is **not** acceptable:
wxChar* foo = _( “this is a long string broken ”
L“into pieces for readability” );
// This works with MSVC, is ugly, and is **not** accepted:
wxChar* foo = _( “this is a long string \
broken into pieces for readability” );
~~~~~~~~~~~~~
A second acceptable solution is to simply put the text all on one
line, even if it exceeds the 99 character line length limit. However,
the preferred method is to break strings within the 99 character limit
whenever possible to prevent wrapping.
## 4.5 Trailing Whitespace ## {#trailing_whitespace}
Many programming editors conveniently indent your code for you. Some of
them do it rather poorly and leave trailing whitespace. Thankfully, most
editors come with a remove trailing whitespace macro or at least a
setting to make trailing whitespace visible so you can see it and
manually remove it. Trailing whitespace is known to break some text
parsing tools. It also leads to unnecessary diffs in the version control
system. Please remove trailing whitespace.
## 4.6 Multiple Statements per Line ## {#multiple_statements_per_line}
It is generally preferred that each statement be placed on its own line.
This is especially true for statements without keywords.
**Example**
~~~~~~~~~~~~~{.cpp}
x=1; y=2; z=3; // Bad, should be on separate lines.
~~~~~~~~~~~~~
## 4.7 Braces ## {#braces}
Braces should be placed on the line proceeding the keyword and indented
to the same level. It is not necessary to use braces if there is only a
single line statement after the keyword. In the case of if..else
if..else, indent all to the same level.
**Example**
~~~~~~~~~~~~~{.cpp}
void function()
{
if( foo )
{
statement1;
statement2;
}
else if( bar )
{
statement3;
statement4;
}
else
statement5;
}
~~~~~~~~~~~~~
## 4.8 Parenthesis ## {#parenthesis}
Parenthesis should be placed immediately after function names and
keywords. Spaces should be placed after the opening parenthesis, before
the closing parenthesis, and between the comma and the next argument in
functions. No space is needed if a function has no arguments.
**Example**
~~~~~~~~~~~~~{.cpp}
void Function( int aArg1, int aArg2 )
{
while( busy )
{
if( a || b || c )
doSomething();
else
doSomethingElse();
}
}
~~~~~~~~~~~~~
## 4.9 Switch Formatting ## {#switch}
The case statement is to be indented to the same level as the switch.
**Example**
~~~~~~~~~~~~~{.cpp}
switch( foo )
{
case 1:
doOne();
break;
case 2:
doTwo();
// Fall through.
default:
doDefault();
}
~~~~~~~~~~~~~
# 5. License Statement # {#license_statement}
There is a the file copyright.h which you can copy into the top of
your new source files and edit the \<author\> field. KiCad depends on
the copyright enforcement capabilities of copyright law, and this
means that source files must be copyrighted and not be released into
the public domain. Each source file has one or more owners.
# 6. Header Files # {#header_files}
Project \*.h source files should:
- contain a license statement
- contain a nested include \#ifndef
- be fully self standing and not depend on other headers that are not
included within it.
The license statement was described above.
## 6.1 Nested Include #ifndef ## {#nested_include}
Each header file should include an \#ifndef which is commonly used to
prevent compiler errors in the case where the header file is seen
multiple times in the code stream presented to the compiler. Just
after the license statement, at the top of the file there should be
lines similar to these (but with a filename specific token other than
`RICHIO_H_`):
~~~~~~~~~~~~~{.cpp}
#ifndef RICHIO_H_
#define RICHIO_H_
~~~~~~~~~~~~~
And at the very bottom of the header file, use a line like this one:
~~~~~~~~~~~~~{.cpp}
#endif // RICHIO_H_
~~~~~~~~~~~~~
The \#ifndef wrapper begins after the license statement, and ends at
the very bottom of the file. It is important that it wrap any nested
\#include statements, so that the compiler can skip them if the
\#ifndef evaluates to false, which will reduce compilation time.
## 6.2 Headers Without Unsatisfied Dependencies ## {#header_depends}
Any header file should include other headers that it depends on. (Note:
KiCad is not at this point now, but this section is a goal of the
project.)
It should be possible to run the compiler on any header file within the
project, and with proper include paths being passed to the compiler, the
header file should compile without error.
**Example**
$ cd /svn/kicad/testing.checkout/include
$ g++ wx-config --cxxflags -I . xnode.h -o /tmp/junk
Such structuring of the header files removes the need within a client
\*.cpp file to include some project header file before some other project
header file. (A client \*.cpp file is one that intends to **use, not
implement,** the public API exposed within the header file.)
Client code should not have to piece together things that a header file
wishes to expose. The exposing header file should be viewed as a fully
sufficient **ticket to use** the public API of that header file.
This is not saying anything about how much to expose, only that that
which is exposed needs to be fully usable merely by including the header
file that exposes it, with no additional includes.
For situations where there is a class header file and an
implementation \*.cpp file, it is desirable to hide as much of the
private implementation as is practical and any header file that is not
needed as part of the public API can and should be included only in
the implementation \*.cpp file. However, the number one concern of
this section is that client (using) code can use the public API which
is exposed in the header file, merely by including that one header
file.
# 7. I Wrote X Lines of Code Before I Read This Document # {#x_lines}
It's OK. We all make mistakes. Fortunately, KiCad provides a
configuration file for the code beautifier uncrustify. Uncrustify won't
fix your naming problems but it does a pretty decent job of formatting
your source code. There are a few places where uncrustify makes some
less than ideal indentation choices. It struggles with the string
declaration macros wxT(“”) and \_(“”) and functions used as arguments to
other functions. After you uncrustify your source code, please review the
indentation for any glaring errors and manually fix them. See the
uncrustify [website][uncrustify] for more information.
[uncrustify]: http://uncrustify.sourceforge.net/
# 8. Show Me an Example # {#show_me_an_example}
Nothing drives the point home like an example. The source file richio.h
below was taken directly from the KiCad source.
~~~~~~~~~~~~~{.cpp}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2007 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 RICHIO_H_
#define RICHIO_H_
// This file defines 3 classes useful for working with DSN text files and is named
// "richio" after its author, Richard Hollenbeck, aka Dick Hollenbeck.
#include <string>
#include <vector>
// I really did not want to be dependent on wxWidgets in richio
// but the errorText needs to be wide char so wxString rules.
#include <wx/wx.h>
#include <cstdio> // FILE
/*/** */*
* Struct IOError
* is a class used to hold an error message and may be used to throw exceptions
* containing meaningful error messages.
*/
struct IOError
{
wxString errorText;
IOError( const wxChar* aMsg ) :
errorText( aMsg )
{
}
IOError( const wxString& aMsg ) :
errorText( aMsg )
{
}
};
/*/** */*
* Class LINE_READER
* reads single lines of text into its buffer and increments a line number counter.
* It throws an exception if a line is too long.
*/
class LINE_READER
{
protected:
FILE* fp;
int lineNum;
unsigned maxLineLength;
unsigned length;
char* line;
unsigned capacity;
public:
/*/** */*
* Constructor LINE_READER
* takes an open FILE and the size of the desired line buffer.
* @param aFile An open file in "ascii" mode, not binary mode.
* @param aMaxLineLength The number of bytes to use in the line buffer.
*/
LINE_READER( FILE* aFile, unsigned aMaxLineLength );
~LINE_READER()
{
delete[] line;
}
/*
int CharAt( int aNdx )
{
if( (unsigned) aNdx < capacity )
return (char) (unsigned char) line[aNdx];
return -1;
}
*/
/*/** */*
* Function ReadLine
* reads a line of text into the buffer and increments the line number
* counter. If the line is larger than the buffer size, then an exception
* is thrown.
* @return int - The number of bytes read, 0 at end of file.
* @throw IOError only when a line is too long.
*/
int ReadLine() throw (IOError);
operator char* ()
{
return line;
}
int LineNumber()
{
return lineNum;
}
unsigned Length()
{
return length;
}
};
/*/** */*
* Class OUTPUTFORMATTER
* is an interface (abstract class) used to output ASCII text in a convenient
* way. The primary interface is printf() like but with support for indentation
* control. The destination of the 8 bit wide text is up to the implementer.
* If you want to output a wxString, then use CONV_TO_UTF8() on it before passing
* it as an argument to Print().
* <p>
* Since this is an abstract interface, only classes derived from this one
* will be the implementations.
*/
class OUTPUTFORMATTER
{
#if defined(__GNUG__) // The GNU C++ compiler defines this
// When used on a C++ function, we must account for the "this" pointer,
// so increase the STRING-INDEX and FIRST-TO_CHECK by one.
// See http://docs.freebsd.org/info/gcc/gcc.info.Function_Attributes.html
// Then to get format checking during the compile, compile with -Wall or -Wformat
#define PRINTF_FUNC __attribute__ ((format (printf, 3, 4)))
#else
#define PRINTF_FUNC // nothing
#endif
public:
/*/** */*
* Function Print
* formats and writes text to the output stream.
*
* @param nestLevel The multiple of spaces to preceed the output with.
* @param fmt A printf() style format string.
* @param ... a variable list of parameters that will get blended into
* the output under control of the format string.
* @return int - the number of characters output.
* @throw IOError, if there is a problem outputting, such as a full disk.
*/
virtual int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ) = 0;
/*/** */*
* Function GetQuoteChar
* performs quote character need determination.
* It returns the quote character as a single character string for a given
* input wrapee string. If the wrappee does not need to be quoted,
* the return value is "" (the null string), such as when there are no
* delimiters in the input wrapee string. If you want the quote_char
* to be assuredly not "", then pass in "(" as the wrappee.
* <p>
* Implementations are free to override the default behavior, which is to
* call the static function of the same name.
* @param wrapee A string that might need wrapping on each end.
* @return const char* - the quote_char as a single character string, or ""
* if the wrapee does not need to be wrapped.
*/
virtual const char* GetQuoteChar( const char* wrapee ) = 0;
virtual ~OUTPUTFORMATTER() {}
/*/** */*
* Function GetQuoteChar
* performs quote character need determination according to the Specctra DSN
* specification.
* @param wrapee A string that might need wrapping on each end.
* @param quote_char A single character C string which provides the current
* quote character, should it be needed by the wrapee.
*
* @return const char* - the quote_char as a single character string, or ""
* if the wrapee does not need to be wrapped.
*/
static const char* GetQuoteChar( const char* wrapee, const char* quote_char );
};
/*/** */*
* Class STRINGFORMATTER
* implements OUTPUTFORMATTER to a memory buffer. After Print()ing the
* string is available through GetString()
*/
class STRINGFORMATTER : public OUTPUTFORMATTER
{
std::vector<char> buffer;
std::string mystring;
int sprint( const char* fmt, ... );
int vprint( const char* fmt, va_list ap );
public:
/*/** */*
* Constructor STRINGFORMATTER
* reserves space in the buffer
*/
STRINGFORMATTER( int aReserve = 300 ) :
buffer( aReserve, '\0' )
{
}
/*/** */*
* Function Clear
* clears the buffer and empties the internal string.
*/
void Clear()
{
mystring.clear();
}
/*/** */*
* Function StripUseless
* removes whitespace, '(', and ')' from the mystring.
*/
void StripUseless();
std::string GetString()
{
return mystring;
}
//-----<OUTPUTFORMATTER>------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>-----------------------------------------------
};
#endif // RICHIO_H_
~~~~~~~~~~~~~
# 9. Resources # {#resources}
There are plenty of excellent resources on the Internet on C++ coding
styles and coding do's and don'ts. Here are a few useful ones. In most
cases, the coding styles do not follow the KiCad coding style but there
is plenty of other good information here. Besides, most of them have
some great humor in them enjoyable to read. Who knows, you might even
learn something new.
- [C++ Coding Standard][cppstandard]
- [Linux Kernel Coding Style][kernel]
- [C++ Operator Overloading Guidelines][overloading]
- [Wikipedia's Programming Style Page][style]
[cppstandard]:http://www.possibility.com/Cpp/CppCodingStandard.html
[kernel]:http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/Documentation/CodingStyle
[overloading]:http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
[style]:http://en.wikipedia.org/wiki/Programming_style
......@@ -645,7 +645,8 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = Documentation/development/stable-release-policy.md \
INPUT = Documentation/development/coding-style-policy.md \
Documentation/development/stable-release-policy.md \
Documentation/development/road-map.md \
kicad \
pcbnew \
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
* 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
......@@ -629,6 +629,13 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event )
tmp << wxT( "OFF\n" );
#endif
tmp << wxT( " KICAD_USE_WEBKIT=" );
#ifdef KICAD_USE_WEBKIT
tmp << wxT( "ON\n" );
#else
tmp << wxT( "OFF\n" );
#endif
wxMessageBox( tmp, _("Version Information (copied to the clipboard)") );
wxTheClipboard->SetData( new wxTextDataObject( tmp ) );
......
/*
* 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) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* 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
......@@ -30,7 +30,7 @@
#endif
#ifndef KICAD_BUILD_VERSION
# define KICAD_BUILD_VERSION "(2014-jul-16 BZR unknown)"
# define KICAD_BUILD_VERSION "(after 2015-jan-16 BZR unknown)"
#endif
/**
......
......@@ -212,29 +212,26 @@ void AddUnitSymbol( wxStaticText& Stext, EDA_UNITS_T aUnit )
}
wxArrayString* wxStringSplit( wxString aString, wxChar aSplitter )
void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter )
{
wxArrayString* list = new wxArrayString();
wxString tmp;
while( 1 )
for( unsigned ii = 0; ii < aText.Length(); ii++ )
{
int index = aString.Find( aSplitter );
if( index == wxNOT_FOUND )
break;
if( aText[ii] == aSplitter )
{
aStrings.Add( tmp );
tmp.Clear();
}
wxString tmp;
tmp = aString.Mid( 0, index );
aString = aString.Mid( index + 1, aString.size() - index );
list->Add( tmp );
else
tmp << aText[ii];
}
if( !aString.IsEmpty() )
if( !tmp.IsEmpty() )
{
list->Add( aString );
aStrings.Add( tmp );
}
return list;
}
......
......@@ -490,6 +490,7 @@ void PARAM_CFG_LIBNAME_LIST::ReadParam( wxConfigBase* aConfig ) const
id_lib << indexlib;
indexlib++;
libname = aConfig->Read( id_lib, wxT( "" ) );
if( libname.IsEmpty() )
break;
// file names are stored using Unix notation
......
......@@ -636,6 +636,7 @@ void PLOTTER::Text( const wxPoint& aPos,
{
// EDA_TEXT needs for calculations of the position of every
// line according to orientation and justifications
wxArrayString strings;
EDA_TEXT* multilineText = new EDA_TEXT( aText );
multilineText->SetSize( aSize );
multilineText->SetTextPosition( aPos );
......@@ -646,15 +647,15 @@ void PLOTTER::Text( const wxPoint& aPos,
multilineText->SetMultilineAllowed( aMultilineAllowed );
std::vector<wxPoint> positions;
wxArrayString* list = wxStringSplit( aText, '\n' );
positions.reserve( list->Count() );
wxStringSplit( aText, strings, '\n' );
positions.reserve( strings.Count() );
multilineText->GetPositionsOfLinesOfMultilineText(
positions, list->Count() );
positions, strings.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings.Count(); ii++ )
{
wxString& txt = list->Item( ii );
wxString& txt = strings.Item( ii );
DrawGraphicText( NULL, NULL, positions[ii], aColor, txt,
aOrient, aSize,
aH_justify, aV_justify,
......@@ -663,8 +664,8 @@ void PLOTTER::Text( const wxPoint& aPos,
NULL,
this );
}
delete multilineText;
delete list;
}
else
{
......
......@@ -120,23 +120,23 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
{
EDA_RECT rect;
wxPoint pos;
wxArrayString* list = NULL;
wxArrayString strings;
wxString text = GetShownText();
int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness;
int linecount = 1;
if( m_MultilineAllowed )
{
list = wxStringSplit( text, '\n' );
wxStringSplit( text, strings, '\n' );
if ( list->GetCount() ) // GetCount() == 0 for void strings
if ( strings.GetCount() ) // GetCount() == 0 for void strings
{
if( aLine >= 0 && (aLine < (int)list->GetCount()) )
text = list->Item( aLine );
if( aLine >= 0 && (aLine < (int)strings.GetCount()) )
text = strings.Item( aLine );
else
text = list->Item( 0 );
text = strings.Item( 0 );
linecount = list->GetCount();
linecount = strings.GetCount();
}
}
......@@ -157,19 +157,17 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
rect.Move( wxPoint( 0, -extra_dy / 2 ) ); // move origin by the half extra interval
// for multiline texts and aLine < 0, merge all rectangles
if( m_MultilineAllowed && list && aLine < 0 )
if( m_MultilineAllowed && aLine < 0 )
{
for( unsigned ii = 1; ii < list->GetCount(); ii++ )
for( unsigned ii = 1; ii < strings.GetCount(); ii++ )
{
text = list->Item( ii );
text = strings.Item( ii );
dx = LenSize( text );
textsize.x = std::max( textsize.x, dx );
textsize.y += dy;
}
}
delete list;
rect.SetSize( textsize );
/* Now, calculate the rect origin, according to text justification
......@@ -272,19 +270,18 @@ void EDA_TEXT::Draw( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset,
if( m_MultilineAllowed )
{
std::vector<wxPoint> positions;
wxArrayString* list = wxStringSplit( GetShownText(), '\n' );
positions.reserve( list->Count() );
wxArrayString strings;
wxStringSplit( GetShownText(), strings, '\n' );
positions.reserve( strings.Count() );
GetPositionsOfLinesOfMultilineText(positions, list->Count() );
GetPositionsOfLinesOfMultilineText(positions, strings.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings.Count(); ii++ )
{
wxString& txt = list->Item( ii );
wxString& txt = strings.Item( ii );
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
aDrawMode, aFillMode, txt, positions[ii] );
}
delete (list);
}
else
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
......@@ -489,22 +486,21 @@ void EDA_TEXT::TransformTextShapeToSegmentList( std::vector<wxPoint>& aCornerBuf
if( IsMultilineAllowed() )
{
wxArrayString* list = wxStringSplit( GetShownText(), '\n' );
wxArrayString strings_list;
wxStringSplit( GetShownText(), strings_list, wxChar('\n') );
std::vector<wxPoint> positions;
positions.reserve( list->Count() );
GetPositionsOfLinesOfMultilineText( positions, list->Count() );
positions.reserve( strings_list.Count() );
GetPositionsOfLinesOfMultilineText( positions,strings_list.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
wxString txt = list->Item( ii );
wxString txt = strings_list.Item( ii );
DrawGraphicText( NULL, NULL, positions[ii], color,
txt, GetOrientation(), size,
GetHorizJustify(), GetVertJustify(),
GetThickness(), IsItalic(),
true, addTextSegmToBuffer );
}
delete list;
}
else
{
......
......@@ -171,7 +171,7 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB,
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
bool col = aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2);
bool col = aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2);
if( col && aNeedMTV )
{
......@@ -210,134 +210,134 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, in
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
return aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2 );
return aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2 );
}
static inline bool Collide( const SHAPE_SEGMENT& aA, const SHAPE_SEGMENT& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
return aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 );
return aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 );
}
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_SEGMENT& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
if( aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 ) )
return true;
if( aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 ) )
return true;
return false;
return false;
}
template<class ShapeAType, class ShapeBType>
template<class ShapeAType, class ShapeBType>
inline bool CollCase( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{
return Collide (*static_cast<const ShapeAType*>( aA ),
*static_cast<const ShapeBType*>( aB ),
aClearance, aNeedMTV, aMTV);
return Collide (*static_cast<const ShapeAType*>( aA ),
*static_cast<const ShapeBType*>( aB ),
aClearance, aNeedMTV, aMTV);
}
template<class ShapeAType, class ShapeBType>
template<class ShapeAType, class ShapeBType>
inline bool CollCaseReversed ( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{
bool rv = Collide (*static_cast<const ShapeBType*>( aB ),
*static_cast<const ShapeAType*>( aA ),
aClearance, aNeedMTV, aMTV);
if(rv && aNeedMTV)
if(rv && aNeedMTV)
aMTV = -aMTV;
return rv;
}
bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{
switch( aA->Type() )
{
case SH_RECT:
switch( aB->Type() )
{
case SH_CIRCLE:
return CollCase<SHAPE_RECT, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
case SH_CIRCLE:
switch( aB->Type() )
{
case SH_RECT:
{
switch( aA->Type() )
{
case SH_RECT:
switch( aB->Type() )
{
case SH_CIRCLE:
return CollCase<SHAPE_RECT, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
case SH_CIRCLE:
switch( aB->Type() )
{
case SH_RECT:
return CollCaseReversed<SHAPE_CIRCLE, SHAPE_RECT>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return CollCase<SHAPE_CIRCLE, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return CollCase<SHAPE_CIRCLE, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
case SH_SEGMENT:
return CollCase<SHAPE_CIRCLE, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
break;
}
case SH_LINE_CHAIN:
switch( aB->Type() )
{
case SH_RECT:
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
switch( aB->Type() )
{
case SH_RECT:
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
default:
break;
}
case SH_SEGMENT:
switch( aB->Type() )
{
case SH_RECT:
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
switch( aB->Type() )
{
case SH_RECT:
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
case SH_CIRCLE:
return CollCaseReversed<SHAPE_SEGMENT, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_SEGMENT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_SEGMENT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
default:
break;
}
default:
break;
}
default:
break;
}
bool unsupported_collision = true;
bool unsupported_collision = true;
(void) unsupported_collision; // make gcc quiet
assert( unsupported_collision == false );
assert( unsupported_collision == false );
return false;
return false;
}
......
......@@ -51,23 +51,20 @@ void HTML_MESSAGE_BOX::ListClear()
void HTML_MESSAGE_BOX::ListSet( const wxString& aList )
{
// wxArrayString* wxStringSplit( wxString txt, wxChar splitter );
wxArrayString* strings_list = wxStringSplit( aList, wxChar( '\n' ) );
wxArrayString strings_list;
wxStringSplit( aList, strings_list, wxChar( '\n' ) );
wxString msg = wxT( "<ul>" );
for ( unsigned ii = 0; ii < strings_list->GetCount(); ii++ )
for ( unsigned ii = 0; ii < strings_list.GetCount(); ii++ )
{
msg += wxT( "<li>" );
msg += strings_list->Item( ii ) + wxT( "</li>" );
msg += strings_list.Item( ii ) + wxT( "</li>" );
}
msg += wxT( "</ul>" );
m_htmlWindow->AppendToPage( msg );
delete strings_list;
}
......
......@@ -331,8 +331,14 @@ bool PROJECT::ConfigLoad( const SEARCH_STACK& aSList, const wxString& aGroupNam
m_pro_date_and_time = timestamp;
// We do not want expansion of env var values when reading our project config file
bool state = cfg.get()->IsExpandingEnvVars();
cfg.get()->SetExpandEnvVars( false );
wxConfigLoadParams( cfg.get(), aParams, aGroupName );
cfg.get()->SetExpandEnvVars( state );
return true;
}
......
......@@ -8,7 +8,7 @@ endif()
add_definitions( -DCVPCB )
if( KICAD_USE_WEBKITT AND BUILD_GITHUB_PLUGIN )
if( KICAD_USE_WEBKIT AND BUILD_GITHUB_PLUGIN )
set( WEBVIEWER_WXLIB "webviewer" )
add_definitions( -DKICAD_USE_WEBKIT )
endif()
......@@ -31,6 +31,8 @@ set( CVPCB_DIALOGS
dialogs/fp_conflict_assignment_selector.cpp
dialogs/dialog_display_options.cpp
dialogs/dialog_display_options_base.cpp
dialogs/dialog_config_equfiles_base.cpp
dialogs/dialog_config_equfiles.cpp
../pcbnew/dialogs/dialog_fp_lib_table.cpp
../pcbnew/dialogs/dialog_fp_lib_table_base.cpp
../pcbnew/dialogs/dialog_fp_plugin_options.cpp
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
* 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
......@@ -25,13 +25,16 @@
* @file autosel.cpp
*/
// Routines for automatic selection of modules.
// This file handle automatic selection of footprints, from .equ files which give
// a footprint FPID associated to a component value.
// Thse assiciations have this form:
// 'FT232BL' 'QFP:LQFP-32_7x7mm_Pitch0.8mm'
#include <fctsys.h>
#include <common.h>
#include <kiface_i.h>
#include <project.h>
#include <confirm.h>
#include <gestfich.h>
#include <pgm_base.h>
#include <kicad_string.h>
......@@ -40,24 +43,10 @@
#include <cvpcb.h>
#include <cvpcb_mainframe.h>
#include <cvstruct.h>
#include <autosel.h>
#define QUOTE '\''
#define FMT_TITLE_LIB_LOAD_ERROR _( "Library Load Error" )
class FOOTPRINT_ALIAS
{
public:
int m_Type;
wxString m_Name;
wxString m_FootprintName;
FOOTPRINT_ALIAS() { m_Type = 0; }
};
typedef boost::ptr_vector< FOOTPRINT_ALIAS > FOOTPRINT_ALIAS_LIST;
/*
* read the string between quotes and put it in aTarget
......@@ -82,45 +71,48 @@ wxString GetQuotedText( wxString & text )
}
void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
// A sort compare function, used to sort a FOOTPRINT_EQUIVALENCE_LIST by cmp values
// (m_ComponentValue member)
bool sortListbyCmpValue( const FOOTPRINT_EQUIVALENCE& ref, const FOOTPRINT_EQUIVALENCE& test )
{
FOOTPRINT_ALIAS_LIST aliases;
FOOTPRINT_ALIAS* alias;
COMPONENT* component;
wxFileName fn;
wxString msg, tmp;
char Line[1024];
FILE* file;
size_t ii;
return ref.m_ComponentValue.Cmp( test.m_ComponentValue ) >= 0;
}
SEARCH_STACK& search = Kiface().KifaceSearch();
// read the .equ files and populate the list of equvalents
int CVPCB_MAINFRAME::buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList, wxString * aErrorMessages )
{
char Line[1024];
int error_count = 0;
FILE* file;
wxFileName fn;
wxString tmp, error_msg;
if( m_netlist.IsEmpty() )
return;
SEARCH_STACK& search = Kiface().KifaceSearch();
// Find equivalents in all available files.
for( ii = 0; ii < m_AliasLibNames.GetCount(); ii++ )
// Find equivalences in all available files, and populates the
// equiv_List with all equivalences found in .equ files
for( unsigned ii = 0; ii < m_EquFilesNames.GetCount(); ii++ )
{
fn = m_AliasLibNames[ii];
if( !fn.HasExt() )
{
fn.SetExt( FootprintAliasFileExtension );
// above fails if filename has more than one point
}
else
{
fn.SetExt( fn.GetExt() + wxT( "." ) + FootprintAliasFileExtension );
}
fn = wxExpandEnvVars( m_EquFilesNames[ii] );
tmp = search.FindValidPath( fn.GetFullPath() );
if( !tmp )
{
msg.Printf( _( "Footprint alias library file '%s' could not be found in the "
"default search paths." ),
GetChars( fn.GetFullName() ) );
wxMessageBox( msg, FMT_TITLE_LIB_LOAD_ERROR, wxOK | wxICON_ERROR );
error_count++;
if( aErrorMessages )
{
error_msg.Printf( _( "Equ file '%s' could not be found in the "
"default search paths." ),
GetChars( fn.GetFullName() ) );
if( ! aErrorMessages->IsEmpty() )
*aErrorMessages << wxT("\n\n");
*aErrorMessages += error_msg;
}
continue;
}
......@@ -128,8 +120,18 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
if( file == NULL )
{
msg.Printf( _( "Error opening alias library '%s'." ), GetChars( tmp ) );
wxMessageBox( msg, FMT_TITLE_LIB_LOAD_ERROR, wxOK | wxICON_ERROR );
error_count++;
if( aErrorMessages )
{
error_msg.Printf( _( "Error opening equ file '%s'." ), GetChars( tmp ) );
if( ! aErrorMessages->IsEmpty() )
*aErrorMessages << wxT("\n\n");
*aErrorMessages += error_msg;
}
continue;
}
......@@ -150,21 +152,46 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
value.Replace( wxT( " " ), wxT( "_" ) );
alias = new FOOTPRINT_ALIAS();
alias->m_Name = value;
alias->m_FootprintName = footprint;
aliases.push_back( alias );
FOOTPRINT_EQUIVALENCE* equivItem = new FOOTPRINT_EQUIVALENCE();
equivItem->m_ComponentValue = value;
equivItem->m_FootprintFPID = footprint;
aList.push_back( equivItem );
}
fclose( file );
}
// Display the number of footprint aliases.
msg.Printf( _( "%d footprint aliases found." ), aliases.size() );
return error_count;
}
void CVPCB_MAINFRAME::AutomaticFootprintMatching( wxCommandEvent& event )
{
FOOTPRINT_EQUIVALENCE_LIST equiv_List;
COMPONENT* component;
wxString msg, error_msg;
size_t ii;
if( m_netlist.IsEmpty() )
return;
if( buildEquivalenceList( equiv_List, &error_msg ) )
wxMessageBox( error_msg, _( "Equ files Load Error" ), wxOK | wxICON_WARNING, this );
// Sort the association list by component value.
// When sorted, find duplicate definitions (i.e. 2 or more items
// having the same component value) is more easy.
std::sort( equiv_List.begin(), equiv_List.end(), sortListbyCmpValue );
// Display the number of footprint/component equivalences.
msg.Printf( _( "%d footprint/cmp equivalences found." ), equiv_List.size() );
SetStatusText( msg, 0 );
// Now, associe each free component with a footprint, when the association
// is found in list
m_skipComponentSelect = true;
ii = 0;
error_msg.Empty();
for( unsigned kk = 0; kk < m_netlist.GetCount(); kk++ )
{
......@@ -173,19 +200,44 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
bool found = false;
m_compListBox->SetSelection( ii++, true );
if( !component->GetFPID().empty() )
if( !component->GetFPID().empty() ) // the component has already a footprint
continue;
BOOST_FOREACH( FOOTPRINT_ALIAS& alias, aliases )
// Here a first attempt is made. We can have multiple equivItem of the same value.
// When happens, using the footprint filter of components can remove the ambiguity by
// filtering equivItem so one can use multiple equiv_List (for polar and
// nonpolar caps for example)
for( unsigned idx = 0; idx < equiv_List.size(); idx++ )
{
FOOTPRINT_EQUIVALENCE& equivItem = equiv_List[idx];
if( alias.m_Name.CmpNoCase( component->GetValue() ) != 0 )
if( equivItem.m_ComponentValue.CmpNoCase( component->GetValue() ) != 0 )
continue;
// filter alias so one can use multiple aliases (for polar and
// nonpolar caps for example)
const FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( alias.m_FootprintName );
const FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( equivItem.m_FootprintFPID );
bool equ_is_unique = true;
unsigned next = idx+1;
unsigned previous = idx-1;
if( next < equiv_List.size() &&
equivItem.m_ComponentValue == equiv_List[next].m_ComponentValue )
equ_is_unique = false;
if( previous >= 0 &&
equivItem.m_ComponentValue == equiv_List[previous].m_ComponentValue )
equ_is_unique = false;
// If the equivalence is unique, no ambiguity: use the association
if( module && equ_is_unique )
{
SetNewPkg( equivItem.m_FootprintFPID );
found = true;
break;
}
// The equivalence is not unique: use the footprint filter to try to remove
// ambiguity
if( module )
{
size_t filtercount = component->GetFootprintFilters().GetCount();
......@@ -201,31 +253,38 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
msg.Printf( _( "Component %s: footprint %s not found in any of the project "
"footprint libraries." ),
GetChars( component->GetReference() ),
GetChars( alias.m_FootprintName ) );
wxMessageBox( msg, _( "CvPcb Error" ), wxOK | wxICON_ERROR, this );
GetChars( equivItem.m_FootprintFPID ) );
if( ! error_msg.IsEmpty() )
error_msg << wxT("\n\n");
error_msg += msg;
}
if( found )
{
SetNewPkg( alias.m_FootprintName );
SetNewPkg( equivItem.m_FootprintFPID );
break;
}
}
if( found )
continue;
// obviously the last chance: there's only one filter matching one footprint
if( !found && 1 == component->GetFootprintFilters().GetCount() )
if( 1 == component->GetFootprintFilters().GetCount() )
{
// we do not need to analyse wildcards: single footprint do not
// contain them and if there are wildcards it just will not match any
const FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( component->GetFootprintFilters()[0] );
if( module )
{
SetNewPkg( component->GetFootprintFilters()[0] );
}
}
}
if( !error_msg.IsEmpty() )
wxMessageBox( error_msg, _( "CvPcb Warning" ), wxOK | wxICON_WARNING, this );
m_skipComponentSelect = false;
}
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* 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
*/
#ifndef AUTOSEL_H
#define AUTOSEL_H
// A helper class to handle info read in .equ files, which gives a footprint FPID
// corresponding to a component value.
// Each line is something like:
// 'FT232BL' 'QFP:LQFP-32_7x7mm_Pitch0.8mm'
//
class FOOTPRINT_EQUIVALENCE
{
public:
wxString m_ComponentValue; // The value of a component
wxString m_FootprintFPID; // the footprint FPID corresponding to this value
FOOTPRINT_EQUIVALENCE() {}
};
typedef boost::ptr_vector< FOOTPRINT_EQUIVALENCE > FOOTPRINT_EQUIVALENCE_LIST;
#endif // ifndef AUTOSEL_H
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007 Jean-Pierre Charras, jean-pierre.charras
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
......@@ -50,7 +50,7 @@ PARAM_CFG_ARRAY& CVPCB_MAINFRAME::GetProjectFileParameters()
m_projectFileParams.push_back( new PARAM_CFG_BASE( GROUP_PCB_LIBS, PARAM_COMMAND_ERASE ) );
m_projectFileParams.push_back( new PARAM_CFG_LIBNAME_LIST(
wxT( "EquName" ), &m_AliasLibNames, GROUP_CVP_EQU ) );
wxT( "EquName" ), &m_EquFilesNames, GROUP_CVP_EQU ) );
m_projectFileParams.push_back( new PARAM_CFG_WXSTRING(
wxT( "NetIExt" ), &m_NetlistFileExtension ) );
......@@ -64,9 +64,8 @@ void CVPCB_MAINFRAME::LoadProjectFile()
PROJECT& prj = Prj();
m_ModuleLibNames.Clear();
m_AliasLibNames.Clear();
m_EquFilesNames.Clear();
// was: Pgm().ReadProjectConfig( fn.GetFullPath(), GROUP, GetProjectFileParameters(), false );
prj.ConfigLoad( Kiface().KifaceSearch(), GROUP_CVP, GetProjectFileParameters() );
if( m_NetlistFileExtension.IsEmpty() )
......@@ -77,26 +76,14 @@ void CVPCB_MAINFRAME::LoadProjectFile()
void CVPCB_MAINFRAME::SaveProjectFile( wxCommandEvent& aEvent )
{
PROJECT& prj = Prj();
wxFileName fn = prj.AbsolutePath( m_NetlistFileName.GetFullPath() );
fn.SetExt( ProjectFileExtension );
if( aEvent.GetId() == ID_SAVE_PROJECT_AS || !m_NetlistFileName.IsOk() )
{
wxFileDialog dlg( this, _( "Save Project File" ), fn.GetPath(),
wxEmptyString, ProjectFileWildcard, wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL )
return;
fn = dlg.GetPath();
if( !fn.HasExt() )
fn.SetExt( ProjectFileExtension );
}
SetTitle( wxString::Format( _( "Project file: '%s'" ), GetChars( prj.GetProjectFullName() ) ) );
wxFileName fn = prj.GetProjectFullName();
if( !IsWritable( fn ) )
{
wxMessageBox( _( "Project file '%s' is not writable" ), fn.GetFullPath() );
return;
}
wxString pro_name = fn.GetFullPath();
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
*
......@@ -69,8 +69,8 @@ BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME )
EVT_MENU( wxID_HELP, CVPCB_MAINFRAME::GetKicadHelp )
EVT_MENU( wxID_ABOUT, CVPCB_MAINFRAME::GetKicadAbout )
EVT_MENU( ID_SAVE_PROJECT, CVPCB_MAINFRAME::SaveProjectFile )
EVT_MENU( ID_SAVE_PROJECT_AS, CVPCB_MAINFRAME::SaveProjectFile )
EVT_MENU( ID_CVPCB_CONFIG_KEEP_OPEN_ON_SAVE, CVPCB_MAINFRAME::OnKeepOpenOnSave )
EVT_MENU( ID_CVPCB_EQUFILES_LIST_EDIT, CVPCB_MAINFRAME::OnEditEquFilesList )
// Toolbar events
EVT_TOOL( ID_CVPCB_QUIT, CVPCB_MAINFRAME::OnQuit )
......@@ -80,7 +80,7 @@ BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME )
EVT_TOOL( ID_CVPCB_GOTO_FIRSTNA, CVPCB_MAINFRAME::ToFirstNA )
EVT_TOOL( ID_CVPCB_GOTO_PREVIOUSNA, CVPCB_MAINFRAME::ToPreviousNA )
EVT_TOOL( ID_CVPCB_DEL_ASSOCIATIONS, CVPCB_MAINFRAME::DelAssociations )
EVT_TOOL( ID_CVPCB_AUTO_ASSOCIE, CVPCB_MAINFRAME::AssocieModule )
EVT_TOOL( ID_CVPCB_AUTO_ASSOCIE, CVPCB_MAINFRAME::AutomaticFootprintMatching )
EVT_TOOL( ID_PCB_DISPLAY_FOOTPRINT_DOC, CVPCB_MAINFRAME::DisplayDocFile )
EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST,
CVPCB_MAINFRAME::OnSelectFilteringFootprint )
......@@ -160,6 +160,7 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_auimgr.SetManagedWindow( this );
UpdateTitle();
EDA_PANEINFO horiz;
horiz.HorizontalToolbarPane();
......@@ -369,10 +370,12 @@ void CVPCB_MAINFRAME::ToPreviousNA( wxCommandEvent& event )
void CVPCB_MAINFRAME::SaveQuitCvpcb( wxCommandEvent& aEvent )
{
if( aEvent.GetId() == wxID_SAVEAS )
m_NetlistFileName.Clear();
wxString fullFilename;
if( aEvent.GetId() != wxID_SAVEAS )
fullFilename = m_NetlistFileName.GetFullPath();
if( SaveCmpLinkFile( m_NetlistFileName.GetFullPath() ) > 0 )
if( SaveCmpLinkFile( fullFilename ) > 0 )
{
m_modified = false;
......@@ -684,32 +687,33 @@ void CVPCB_MAINFRAME::DisplayStatus()
}
msg.Empty();
wxString filters;
if( m_footprintListBox )
{
if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST ) )
msg = _( "key words" );
filters = _( "key words" );
if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST ) )
{
if( !msg.IsEmpty() )
msg += wxT( ", " );
if( !filters.IsEmpty() )
filters += wxT( "+" );
msg += _( "pin count" );
filters += _( "pin count" );
}
if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST ) )
{
if( !msg.IsEmpty() )
msg += wxT( ", " );
if( !filters.IsEmpty() )
filters += wxT( "+" );
msg += _( "library" );
filters += _( "library" );
}
if( msg.IsEmpty() )
if( filters.IsEmpty() )
msg = _( "No filtering" );
else
msg = _( "Filtered by " ) + msg;
msg.Printf( _( "Filtered by %s" ), GetChars( filters ) );
msg << wxT( ": " ) << m_footprintListBox->GetCount();
......@@ -744,18 +748,21 @@ bool CVPCB_MAINFRAME::LoadFootprintFiles()
void CVPCB_MAINFRAME::UpdateTitle()
{
wxString title = wxString::Format( wxT( "Cvpcb %s " ), GetChars( GetBuildVersion() ) );
PROJECT& prj = Prj();
wxFileName fn = prj.GetProjectFullName();
if( m_NetlistFileName.IsOk() && m_NetlistFileName.FileExists() )
if( fn.IsOk() && !prj.GetProjectFullName().IsEmpty() && fn.FileExists() )
{
title += m_NetlistFileName.GetFullPath();
title += wxString::Format( _("Project: '%s' (netlist: '%s')"),
GetChars( fn.GetFullPath() ),
GetChars( m_NetlistFileName.GetFullName() )
);
if( !m_NetlistFileName.IsFileWritable() )
if( !fn.IsFileWritable() )
title += _( " [Read Only]" );
}
else
{
title += _( "[no file]" );
}
title += _( "[no project]" );
SetTitle( title );
}
......
......@@ -51,10 +51,10 @@
COLORS_DESIGN_SETTINGS g_ColorsSettings;
// Constant string definitions for CvPcb
const wxString FootprintAliasFileExtension( wxT( "equ" ) );
const wxString EquFileExtension( wxT( "equ" ) );
// Wildcard for schematic retroannotation (import footprint names in schematic):
const wxString FootprintAliasFileWildcard( _( "KiCad footprint alias files (*.equ)|*.equ" ) );
const wxString EquFilesWildcard( _( "Component/footprint equ files (*.equ)|*.equ" ) );
#if 0 // add this logic to OpenProjectFiles()
......
......@@ -36,8 +36,8 @@
#define LISTB_STYLE ( wxSUNKEN_BORDER | wxLC_NO_HEADER | wxLC_REPORT | wxLC_VIRTUAL | \
wxLC_SINGLE_SEL | wxVSCROLL | wxHSCROLL )
extern const wxString FootprintAliasFileExtension;
extern const wxString FootprintAliasFileWildcard;
extern const wxString EquFileExtension;
extern const wxString EquFilesWildcard;
#endif /* __CVPCB_H__ */
......@@ -56,5 +56,6 @@ enum id_cvpcb_frm
ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST,
ID_CVPCB_CONFIG_KEEP_OPEN_ON_SAVE,
ID_CVPCB_LIBRARY_LIST,
ID_CVPCB_EQUFILES_LIST_EDIT,
ID_CVPCB_LIB_TABLE_EDIT
};
......@@ -36,6 +36,7 @@
#include <wxBasePcbFrame.h>
#include <config_params.h>
#include <autosel.h>
/* Forward declarations of all top-level window classes. */
......@@ -66,7 +67,7 @@ public:
wxAuiToolBar* m_mainToolBar;
wxFileName m_NetlistFileName;
wxArrayString m_ModuleLibNames;
wxArrayString m_AliasLibNames;
wxArrayString m_EquFilesNames;
wxString m_NetlistFileExtension;
wxString m_DocModulesFileName;
FOOTPRINT_LIST m_footprints;
......@@ -137,10 +138,16 @@ public:
/**
* Function OnEditLibraryTable
* envokes the footpirnt library table edit dialog.
* envokes the footprint library table edit dialog.
*/
void OnEditFootprintLibraryTable( wxCommandEvent& aEvent );
/**
* Function OnEditEquFilesList
* envokes the equ files list edit dialog.
*/
void OnEditEquFilesList( wxCommandEvent& aEvent );
void OnKeepOpenOnSave( wxCommandEvent& event );
void DisplayModule( wxCommandEvent& event );
......@@ -152,7 +159,7 @@ public:
* format of a line:
* 'cmp_ref' 'footprint_name'
*/
void AssocieModule( wxCommandEvent& event );
void AutomaticFootprintMatching( wxCommandEvent& event );
void DisplayDocFile( wxCommandEvent& event );
......@@ -171,6 +178,7 @@ public:
* @param aFootprintName = the selected footprint
*/
void SetNewPkg( const wxString& aFootprintName );
void BuildCmpListBox();
void BuildFOOTPRINTS_LISTBOX();
void BuildLIBRARY_LISTBOX();
......@@ -286,6 +294,17 @@ public:
COMPONENT* GetSelectedComponent();
private:
/**
* read the .equ files and populate the list of equvalents
* @param aList the list to populate
* @param aErrorMessages is a pointer to a wxString to store error messages
* (can be NULL)
* @return the error count ( 0 = no error)
*/
int buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList, wxString * aErrorMessages = NULL );
DECLARE_EVENT_TABLE()
};
......
/**
* @file dialog_config_equfiles.cpp
*/
/*
* 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) 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
*/
#include <fctsys.h>
#include <pgm_base.h>
#include <common.h>
#include <confirm.h>
#include <gestfich.h>
#include <id.h>
#include <project.h> // For PROJECT_VAR_NAME definition
#include <fp_lib_table.h> // For KISYSMOD definition
#include <cvpcb.h>
#include <cvpcb_mainframe.h>
#include <dialog_config_equfiles.h>
#include <wildcards_and_files_ext.h>
DIALOG_CONFIG_EQUFILES::DIALOG_CONFIG_EQUFILES( CVPCB_MAINFRAME* aParent ) :
DIALOG_CONFIG_EQUFILES_BASE( aParent )
{
m_Parent = aParent;
m_Config = Pgm().CommonSettings();
PROJECT& prj = Prj();
SetTitle( wxString::Format( _( "Project file: '%s'" ), GetChars( prj.GetProjectFullName() ) ) );
Init( );
GetSizer()->SetSizeHints( this );
Center();
}
void CVPCB_MAINFRAME::OnEditEquFilesList( wxCommandEvent& aEvent )
{
DIALOG_CONFIG_EQUFILES dlg( this );
dlg.ShowModal();
}
void DIALOG_CONFIG_EQUFILES::Init()
{
m_sdbSizerOK->SetDefault();
m_ListChanged = false;
m_ListEquiv->InsertItems( m_Parent->m_EquFilesNames, 0 );
if( getEnvVarCount() < 2 )
m_gridEnvVars->AppendRows(2 - getEnvVarCount() );
wxString evValue;
int row = 0;
m_gridEnvVars->SetCellValue( row++, 0, PROJECT_VAR_NAME );
m_gridEnvVars->SetCellValue( row, 0, FP_LIB_TABLE::GlobalPathEnvVariableName() );
for( row = 0; row < getEnvVarCount(); row++ )
{
if( wxGetEnv( m_gridEnvVars->GetCellValue( row, 0 ), &evValue ) )
m_gridEnvVars->SetCellValue( row, 1, evValue );
}
m_gridEnvVars->AutoSizeColumns();
}
void DIALOG_CONFIG_EQUFILES::OnEditEquFile( wxCommandEvent& event )
{
wxString editorname = Pgm().GetEditorName();
if( editorname.IsEmpty() )
{
wxMessageBox( _( "No editor defined in Kicad. Please chose it" ) );
return;
}
wxArrayInt selections;
m_ListEquiv->GetSelections( selections );
wxString fullFileNames, tmp;
for( unsigned ii = 0; ii < selections.GetCount(); ii++ )
{
tmp = m_ListEquiv->GetString( selections[ii] );
fullFileNames << wxT( " \"" ) << wxExpandEnvVars( tmp ) << wxT( "\"" );
m_ListChanged = true;
}
ExecuteFile( this, editorname, fullFileNames );
}
void DIALOG_CONFIG_EQUFILES::OnCancelClick( wxCommandEvent& event )
{
EndModal( wxID_CANCEL );
}
void DIALOG_CONFIG_EQUFILES::OnOkClick( wxCommandEvent& event )
{
// Save new equ file list if the files list was modified
if( m_ListChanged )
{
// Recreate equ list
m_Parent->m_EquFilesNames.Clear();
for( unsigned ii = 0; ii < m_ListEquiv->GetCount(); ii++ )
m_Parent->m_EquFilesNames.Add( m_ListEquiv->GetString( ii ) );
wxCommandEvent evt( ID_SAVE_PROJECT );
m_Parent->SaveProjectFile( evt );
}
EndModal( wxID_OK );
}
void DIALOG_CONFIG_EQUFILES::OnCloseWindow( wxCloseEvent& event )
{
EndModal( wxID_CANCEL );
}
/********************************************************************/
void DIALOG_CONFIG_EQUFILES::OnButtonMoveUp( wxCommandEvent& event )
/********************************************************************/
{
wxArrayInt selections;
m_ListEquiv->GetSelections( selections );
if ( selections.GetCount() <= 0 ) // No selection.
return;
if( selections[0] == 0 ) // The first lib is selected. cannot move up it
return;
wxArrayString libnames = m_ListEquiv->GetStrings();
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
{
int jj = selections[ii];
EXCHG( libnames[jj], libnames[jj-1] );
}
m_ListEquiv->Set( libnames );
// Reselect previously selected names
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
{
int jj = selections[ii];
m_ListEquiv->SetSelection( jj-1 );
}
m_ListChanged = true;
}
/*********************************************************************/
void DIALOG_CONFIG_EQUFILES::OnButtonMoveDown( wxCommandEvent& event )
/*********************************************************************/
{
wxArrayInt selections;
m_ListEquiv->GetSelections( selections );
if ( selections.GetCount() <= 0 ) // No selection.
return;
// The last lib is selected. cannot move down it
if( selections.Last() == int( m_ListEquiv->GetCount()-1 ) )
return;
wxArrayString libnames = m_ListEquiv->GetStrings();
for( int ii = selections.GetCount()-1; ii >= 0; ii-- )
{
int jj = selections[ii];
EXCHG( libnames[jj], libnames[jj+1]);
}
m_ListEquiv->Set( libnames );
// Reselect previously selected names
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
{
int jj = selections[ii];
m_ListEquiv->SetSelection(jj+1);
}
m_ListChanged = true;
}
/* Remove a library to the library list.
* The real list (g_LibName_List) is not changed, so the change can be canceled
*/
void DIALOG_CONFIG_EQUFILES::OnRemoveFiles( wxCommandEvent& event )
{
wxArrayInt selections;
m_ListEquiv->GetSelections( selections );
std::sort( selections.begin(), selections.end() );
for( int ii = selections.GetCount()-1; ii >= 0; ii-- )
{
m_ListEquiv->Delete(selections[ii] );
m_ListChanged = true;
}
}
/* Insert or add a library to the library list:
* The new library is put in list before (insert button) the selection,
* or added (add button) to end of list
*/
void DIALOG_CONFIG_EQUFILES::OnAddFiles( wxCommandEvent& event )
{
wxString equFilename, wildcard;
wxFileName fn;
wildcard = EquFilesWildcard;
wxListBox* list = m_ListEquiv;
// Get a default path to open the file dialog:
wxString libpath;
wxArrayInt selectedRows = m_gridEnvVars->GetSelectedRows();
int row = selectedRows.GetCount() ? selectedRows[0] :
m_gridEnvVars->GetGridCursorRow();
libpath = m_gridEnvVars->GetCellValue( wxGridCellCoords( row, 1 ) );
wxFileDialog FilesDialog( this, _( "Equ files:" ), libpath,
wxEmptyString, wildcard,
wxFD_DEFAULT_STYLE | wxFD_MULTIPLE );
if( FilesDialog.ShowModal() != wxID_OK )
return;
wxArrayString Filenames;
FilesDialog.GetPaths( Filenames );
for( unsigned jj = 0; jj < Filenames.GetCount(); jj++ )
{
fn = Filenames[jj];
equFilename.Empty();
if( isPathRelativeAllowed() ) // try to use relative path
{
for( row = 0; row < getEnvVarCount(); row++ )
{
libpath = m_gridEnvVars->GetCellValue( wxGridCellCoords( row, 1 ) );
if( fn.MakeRelativeTo( libpath ) )
{
equFilename.Printf( wxT("${%s}%c%s"),
GetChars( m_gridEnvVars->GetCellValue( wxGridCellCoords( row, 0 ) ) ),
fn.GetPathSeparator(),
GetChars( fn.GetFullPath() ) );
break;
}
}
}
if( equFilename.IsEmpty() )
equFilename = Filenames[jj];
// Add or insert new library name, if not already in list
if( list->FindString( equFilename, fn.IsCaseSensitive() ) == wxNOT_FOUND )
{
m_ListChanged = true;
equFilename.Replace( wxT("\\"), wxT("/") ); // Use unix separators only.
list->Append( equFilename );
}
else
{
wxString msg;
msg.Printf( _( "File '%s' already exists in list" ), equFilename.GetData() );
DisplayError( this, msg );
}
}
}
/**
* @file dialog_config_equfiles.h
*/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2010-2015 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-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 _DIALOG_CONFIG_EQUFILES_H_
#define _DIALOG_CONFIG_EQUFILES_H_
#include <dialog_config_equfiles_base.h>
class DIALOG_CONFIG_EQUFILES : public DIALOG_CONFIG_EQUFILES_BASE
{
private:
CVPCB_MAINFRAME* m_Parent;
wxConfigBase* m_Config;
wxString m_UserLibDirBufferImg;
bool m_ListChanged;
private:
void Init();
// Virtual event handlers
void OnCloseWindow( wxCloseEvent& event );
void OnOkClick( wxCommandEvent& event );
void OnCancelClick( wxCommandEvent& event );
void OnAddFiles( wxCommandEvent& event );
void OnEditEquFile( wxCommandEvent& event );
void OnRemoveFiles( wxCommandEvent& event );
void OnButtonMoveUp( wxCommandEvent& event );
void OnButtonMoveDown( wxCommandEvent& event );
int getEnvVarCount() // Get the number of rows in env var table
{
return m_gridEnvVars->GetTable()->GetRowsCount();
}
bool isPathRelativeAllowed()
{
return m_rbPathOptionChoice->GetSelection() == 1;
}
public:
DIALOG_CONFIG_EQUFILES( CVPCB_MAINFRAME* parent );
~DIALOG_CONFIG_EQUFILES() {};
};
#endif // _DIALOG_CONFIG_EQUFILES_H_
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 5 2014)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_config_equfiles_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_CONFIG_EQUFILES_BASE::DIALOG_CONFIG_EQUFILES_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( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbEquivChoiceSizer;
sbEquivChoiceSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Footprint/Component equ files (.equ files)") ), wxHORIZONTAL );
wxBoxSizer* bSizerFlist;
bSizerFlist = new wxBoxSizer( wxVERTICAL );
m_ListEquiv = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_HSCROLL|wxLB_NEEDED_SB|wxLB_SINGLE );
m_ListEquiv->SetMinSize( wxSize( 350,-1 ) );
bSizerFlist->Add( m_ListEquiv, 1, wxRIGHT|wxLEFT|wxEXPAND, 5 );
sbEquivChoiceSizer->Add( bSizerFlist, 1, wxEXPAND, 5 );
wxBoxSizer* bSizerButtons;
bSizerButtons = new wxBoxSizer( wxVERTICAL );
m_buttonAddEqu = new wxButton( this, ID_ADD_EQU, _("Add"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_buttonAddEqu, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_buttonRemoveEqu = new wxButton( this, ID_REMOVE_EQU, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonRemoveEqu->SetToolTip( _("Unload the selected library") );
bSizerButtons->Add( m_buttonRemoveEqu, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_buttonMoveUp = new wxButton( this, ID_EQU_UP, _("Move Up"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_buttonMoveUp, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_buttonMoveDown = new wxButton( this, ID_EQU_DOWN, _("Move Down"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_buttonMoveDown, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_buttonEdit = new wxButton( this, wxID_ANY, _("Edit Equ File"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_buttonEdit, 0, wxALL|wxEXPAND, 5 );
sbEquivChoiceSizer->Add( bSizerButtons, 0, wxALIGN_CENTER_VERTICAL, 5 );
bMainSizer->Add( sbEquivChoiceSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerLower;
bSizerLower = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bSizerEnvVar;
bSizerEnvVar = new wxBoxSizer( wxVERTICAL );
m_staticText2 = new wxStaticText( this, wxID_ANY, _("Available environment variables for relative paths:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText2->Wrap( -1 );
bSizerEnvVar->Add( m_staticText2, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_gridEnvVars = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
// Grid
m_gridEnvVars->CreateGrid( 2, 2 );
m_gridEnvVars->EnableEditing( true );
m_gridEnvVars->EnableGridLines( true );
m_gridEnvVars->EnableDragGridSize( false );
m_gridEnvVars->SetMargins( 0, 0 );
// Columns
m_gridEnvVars->EnableDragColMove( false );
m_gridEnvVars->EnableDragColSize( true );
m_gridEnvVars->SetColLabelSize( 25 );
m_gridEnvVars->SetColLabelValue( 0, _("Name") );
m_gridEnvVars->SetColLabelValue( 1, _("Value") );
m_gridEnvVars->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
// Rows
m_gridEnvVars->AutoSizeRows();
m_gridEnvVars->EnableDragRowSize( true );
m_gridEnvVars->SetRowLabelSize( 30 );
m_gridEnvVars->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
// Label Appearance
// Cell Defaults
m_gridEnvVars->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
bSizerEnvVar->Add( m_gridEnvVars, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizerLower->Add( bSizerEnvVar, 1, wxEXPAND, 5 );
wxString m_rbPathOptionChoiceChoices[] = { _("Absolute path"), _("Relative path") };
int m_rbPathOptionChoiceNChoices = sizeof( m_rbPathOptionChoiceChoices ) / sizeof( wxString );
m_rbPathOptionChoice = new wxRadioBox( this, wxID_ANY, _("Path option:"), wxDefaultPosition, wxDefaultSize, m_rbPathOptionChoiceNChoices, m_rbPathOptionChoiceChoices, 1, wxRA_SPECIFY_COLS );
m_rbPathOptionChoice->SetSelection( 1 );
bSizerLower->Add( m_rbPathOptionChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bMainSizer->Add( bSizerLower, 0, wxEXPAND, 5 );
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bMainSizer->Add( m_staticline2, 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, 5 );
this->SetSizer( bMainSizer );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnCloseWindow ) );
m_buttonAddEqu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnAddFiles ), NULL, this );
m_buttonRemoveEqu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnRemoveFiles ), NULL, this );
m_buttonMoveUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnButtonMoveUp ), NULL, this );
m_buttonMoveDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnButtonMoveDown ), NULL, this );
m_buttonEdit->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnEditEquFile ), NULL, this );
m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnCancelClick ), NULL, this );
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnOkClick ), NULL, this );
}
DIALOG_CONFIG_EQUFILES_BASE::~DIALOG_CONFIG_EQUFILES_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnCloseWindow ) );
m_buttonAddEqu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnAddFiles ), NULL, this );
m_buttonRemoveEqu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnRemoveFiles ), NULL, this );
m_buttonMoveUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnButtonMoveUp ), NULL, this );
m_buttonMoveDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnButtonMoveDown ), NULL, this );
m_buttonEdit->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnEditEquFile ), NULL, this );
m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnCancelClick ), NULL, this );
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CONFIG_EQUFILES_BASE::OnOkClick ), NULL, this );
}
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 5 2014)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_CONFIG_EQUFILES_BASE_H__
#define __DIALOG_CONFIG_EQUFILES_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class DIALOG_SHIM;
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/listbox.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/statbox.h>
#include <wx/stattext.h>
#include <wx/grid.h>
#include <wx/radiobox.h>
#include <wx/statline.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_CONFIG_EQUFILES_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_CONFIG_EQUFILES_BASE : public DIALOG_SHIM
{
private:
protected:
enum
{
ID_ADD_EQU = 1000,
ID_REMOVE_EQU,
ID_EQU_UP,
ID_EQU_DOWN
};
wxListBox* m_ListEquiv;
wxButton* m_buttonAddEqu;
wxButton* m_buttonRemoveEqu;
wxButton* m_buttonMoveUp;
wxButton* m_buttonMoveDown;
wxButton* m_buttonEdit;
wxStaticText* m_staticText2;
wxGrid* m_gridEnvVars;
wxRadioBox* m_rbPathOptionChoice;
wxStaticLine* m_staticline2;
wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnCloseWindow( wxCloseEvent& event ) { event.Skip(); }
virtual void OnAddFiles( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemoveFiles( wxCommandEvent& event ) { event.Skip(); }
virtual void OnButtonMoveUp( wxCommandEvent& event ) { event.Skip(); }
virtual void OnButtonMoveDown( wxCommandEvent& event ) { event.Skip(); }
virtual void OnEditEquFile( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_CONFIG_EQUFILES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 454,338 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_CONFIG_EQUFILES_BASE();
};
#endif //__DIALOG_CONFIG_EQUFILES_BASE_H__
/**
* @file dialog_cvpcb_config.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
* 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 <fctsys.h>
#include <wx/tokenzr.h>
#include <pgm_base.h>
#include <common.h>
#include <confirm.h>
#include <gestfich.h>
#include <id.h>
#include <macros.h>
#include <cvpcb.h>
#include <cvpcb_mainframe.h>
#include <dialog_cvpcb_config.h>
#include <wildcards_and_files_ext.h>
DIALOG_CVPCB_CONFIG::DIALOG_CVPCB_CONFIG( CVPCB_MAINFRAME* aParent ) :
DIALOG_CVPCB_CONFIG_FBP( aParent )
{
wxString title;
wxFileName fn = aParent->m_NetlistFileName;
fn.SetExt( ProjectFileExtension );
m_Parent = aParent;
m_Config = Pgm().CommonSettings();
Init( );
title.Format( _( "Project file: '%s'" ), GetChars( fn.GetFullPath() ) );
SetTitle( title );
if( GetSizer() )
{
GetSizer()->SetSizeHints( this );
}
m_sdbSizer2OK->SetDefault();
}
void DIALOG_CVPCB_CONFIG::Init()
{
wxString msg;
SetFocus();
m_LibListChanged = false;
m_LibPathChanged = false;
m_UserLibDirBufferImg = m_Parent->m_UserLibraryPath;
m_ListLibr->InsertItems( m_Parent->m_ModuleLibNames, 0 );
m_ListEquiv->InsertItems( m_Parent->m_AliasLibNames, 0 );
m_TextHelpModulesFileName->SetValue( m_Parent->m_DocModulesFileName );
// Load user libs paths:
wxStringTokenizer Token( m_UserLibDirBufferImg, wxT( ";\n\r" ) );
while( Token.HasMoreTokens() )
{
wxString path = Token.GetNextToken();
if( wxFileName::DirExists( path ) )
m_listUserPaths->Append( path );
}
// Display actual libraries paths:
wxPathList libpaths = Pgm().GetLibraryPathList();
for( unsigned ii = 0; ii < libpaths.GetCount(); ii++ )
{
m_DefaultLibraryPathslistBox->Append( libpaths[ii] );
}
// select the first path after the current path project
if( libpaths.GetCount() > 1 )
m_DefaultLibraryPathslistBox->Select( 1 );
}
void DIALOG_CVPCB_CONFIG::OnCancelClick( wxCommandEvent& event )
{
// Recreate the user lib path
if( m_LibPathChanged )
{
for( unsigned ii = 0; ii < m_ListLibr->GetCount(); ii++ )
Pgm().RemoveLibraryPath( m_listUserPaths->GetString( ii ) );
Pgm().InsertLibraryPath( m_Parent->m_UserLibraryPath, 1 );
}
EndModal( wxID_CANCEL );
}
void DIALOG_CVPCB_CONFIG::OnOkClick( wxCommandEvent& event )
{
m_Parent->m_DocModulesFileName = m_TextHelpModulesFileName->GetValue();
// Recreate the user lib path
if( m_LibPathChanged )
{
m_Parent->m_UserLibraryPath.Empty();
for( unsigned ii = 0; ii < m_listUserPaths->GetCount(); ii++ )
{
if( ii > 0 )
m_Parent->m_UserLibraryPath << wxT( ";" );
m_Parent->m_UserLibraryPath << m_listUserPaths->GetString( ii );
}
}
// Set new active library list if the lib list of if default path list was modified
if( m_LibListChanged || m_LibPathChanged )
{
// Recreate lib list
m_Parent->m_ModuleLibNames.Clear();
for( unsigned ii = 0; ii < m_ListLibr->GetCount(); ii++ )
m_Parent->m_ModuleLibNames.Add( m_ListLibr->GetString( ii ) );
// Recreate equ list
m_Parent->m_AliasLibNames.Clear();
for( unsigned ii = 0; ii < m_ListEquiv->GetCount(); ii++ )
m_Parent->m_AliasLibNames.Add( m_ListEquiv->GetString( ii ) );
m_Parent->LoadFootprintFiles();
m_Parent->BuildFOOTPRINTS_LISTBOX();
m_Parent->BuildLIBRARY_LISTBOX();
}
wxCommandEvent evt( ID_SAVE_PROJECT );
m_Parent->SaveProjectFile( evt );
EndModal( wxID_OK );
}
void DIALOG_CVPCB_CONFIG::OnCloseWindow( wxCloseEvent& event )
{
EndModal( 0 );
}
/********************************************************************/
void DIALOG_CVPCB_CONFIG::OnButtonUpClick( wxCommandEvent& event )
/********************************************************************/
{
wxListBox * list = m_ListLibr;
if( (event.GetId() == ID_EQU_UP) || (event.GetId() == ID_EQU_DOWN) )
{
list = m_ListEquiv;
}
wxArrayInt selections;
list->GetSelections( selections );
if ( selections.GetCount() <= 0 ) // No selection.
return;
if( selections[0] == 0 ) // The first lib is selected. cannot move up it
return;
wxArrayString libnames = list->GetStrings();
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
{
int jj = selections[ii];
EXCHG( libnames[jj], libnames[jj-1] );
}
list->Set( libnames );
// Reselect previously selected names
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
{
int jj = selections[ii];
list->SetSelection( jj-1 );
}
m_LibListChanged = true;
}
/*********************************************************************/
void DIALOG_CVPCB_CONFIG::OnButtonDownClick( wxCommandEvent& event )
/*********************************************************************/
{
wxListBox * list = m_ListLibr;
if( (event.GetId() == ID_EQU_UP) || (event.GetId() == ID_EQU_DOWN) )
{
list = m_ListEquiv;
}
wxArrayInt selections;
list->GetSelections( selections );
if ( selections.GetCount() <= 0 ) // No selection.
return;
// The last lib is selected. cannot move down it
if( selections.Last() == (int)(list->GetCount()-1) )
return;
wxArrayString libnames = list->GetStrings();
for( int ii = selections.GetCount()-1; ii >= 0; ii-- )
{
int jj = selections[ii];
EXCHG( libnames[jj], libnames[jj+1]);
}
list->Set( libnames );
// Reselect previously selected names
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
{
int jj = selections[ii];
list->SetSelection(jj+1);
}
m_LibListChanged = true;
}
/* Remove a library to the library list.
* The real list (g_LibName_List) is not changed, so the change can be canceled
*/
void DIALOG_CVPCB_CONFIG::OnRemoveLibClick( wxCommandEvent& event )
{
wxListBox * list = m_ListEquiv;
if( event.GetId() == ID_REMOVE_LIB )
list = m_ListLibr;
wxArrayInt selections;
list->GetSelections( selections );
for( int ii = selections.GetCount()-1; ii >= 0; ii-- )
{
list->Delete(selections[ii] );
m_LibListChanged = true;
}
}
/* Insert or add a library to the library list:
* The new library is put in list before (insert button) the selection,
* or added (add button) to end of list
* The real list (g_LibName_List) is not changed, so the change can be canceled
*/
void DIALOG_CVPCB_CONFIG::OnAddOrInsertLibClick( wxCommandEvent& event )
{
int ii;
wxString libfilename, wildcard;
wxFileName fn;
bool insert = false;
if( (event.GetId() == ID_INSERT_EQU) || (event.GetId() == ID_INSERT_LIB) )
insert = true;
wildcard = FootprintAliasFileWildcard;
wxListBox* list = m_ListEquiv;
if( (event.GetId() == ID_ADD_LIB) || (event.GetId() == ID_INSERT_LIB) )
{
list = m_ListLibr;
wildcard = LegacyFootprintLibPathWildcard;
}
wxArrayInt selections;
list->GetSelections(selections);
ii = selections.GetCount();
if( ii > 0 )
ii = selections[0];
else
ii = 0;
wxString libpath;
libpath = m_DefaultLibraryPathslistBox->GetStringSelection();
if( libpath.IsEmpty() )
libpath = Pgm().LastVisitedLibraryPath();
wxFileDialog FilesDialog( this, _( "Footprint library files:" ), libpath,
wxEmptyString, wildcard,
wxFD_DEFAULT_STYLE | wxFD_MULTIPLE );
if( FilesDialog.ShowModal() != wxID_OK )
return;
wxArrayString Filenames;
FilesDialog.GetPaths( Filenames );
for( unsigned jj = 0; jj < Filenames.GetCount(); jj++ )
{
fn = Filenames[jj];
if( jj == 0 )
Pgm().SaveLastVisitedLibraryPath( fn.GetPath() );
/* If the library path is already in the library search paths
* list, just add the library name to the list. Otherwise, add
* the library name with the full or relative path.
* the relative path, when possible is preferable,
* because it preserve use of default libraries paths, when the path
* is a sub path of these default paths
*/
libfilename = Pgm().FilenameWithRelativePathInSearchList( fn.GetFullPath() );
// Remove extension:
fn = libfilename;
fn.SetExt( wxEmptyString );
libfilename = fn.GetFullPath();
// Add or insert new library name, if not already in list
if( list->FindString( libfilename, fn.IsCaseSensitive() ) == wxNOT_FOUND )
{
m_LibListChanged = true;
if( ! insert )
list->Append( libfilename );
else
list->Insert( libfilename, ii++ );
}
else
{
wxString msg = wxT( "<" ) + libfilename + wxT( "> : " ) +
_( "Library already in use" );
DisplayError( this, msg );
}
}
}
void DIALOG_CVPCB_CONFIG::OnAddOrInsertPath( wxCommandEvent& event )
{
wxString path = Pgm().LastVisitedLibraryPath();
bool select = EDA_DirectorySelector( _( "Default Path for Libraries" ),
path,
wxDD_DEFAULT_STYLE,
this,
wxDefaultPosition );
if( !select )
return;
if( !wxFileName::DirExists( path ) ) // Should not occurs
return;
// Add or insert path if not already in list
if( m_listUserPaths->FindString( path ) == wxNOT_FOUND )
{
int ipos = m_listUserPaths->GetCount();
if( event.GetId() == ID_INSERT_PATH )
{
if( ipos )
ipos--;
int jj = m_listUserPaths->GetSelection();
if( jj >= 0 )
ipos = jj;
}
// Ask the user if this is a relative path
int diag = wxMessageBox( _( "Use a relative path?" ),
_( "Path type" ),
wxYES_NO | wxICON_QUESTION, this );
if( diag == wxYES )
{ // Make it relative
wxFileName fn = path;
fn.MakeRelativeTo( wxT( "." ) );
path = fn.GetPathWithSep() + fn.GetFullName();
}
m_listUserPaths->Insert( path, ipos );
m_LibPathChanged = true;
Pgm().InsertLibraryPath( path, ipos + 1 );
// Display actual libraries paths:
wxPathList libpaths = Pgm().GetLibraryPathList();
m_DefaultLibraryPathslistBox->Clear();
for( unsigned ii = 0; ii < libpaths.GetCount(); ii++ )
{
m_DefaultLibraryPathslistBox->Append( libpaths[ii] );
}
}
else
{
DisplayError( this, _( "Path already in use" ) );
}
Pgm().SaveLastVisitedLibraryPath( path );
}
void DIALOG_CVPCB_CONFIG::OnRemoveUserPath( wxCommandEvent& event )
{
int ii = m_listUserPaths->GetSelection();
if( ii < 0 )
ii = m_listUserPaths->GetCount() - 1;
if( ii >= 0 )
{
Pgm().RemoveLibraryPath( m_listUserPaths->GetStringSelection() );
m_listUserPaths->Delete( ii );
m_LibPathChanged = true;
}
// Display actual libraries paths:
wxPathList libpaths = Pgm().GetLibraryPathList();
m_DefaultLibraryPathslistBox->Clear();
for( unsigned ii = 0; ii < libpaths.GetCount(); ii++ )
{
m_DefaultLibraryPathslistBox->Append( libpaths[ii] );
}
}
void DIALOG_CVPCB_CONFIG::OnBrowseModDocFile( wxCommandEvent& event )
{
wxString FullFileName;
wxString docpath, filename;
docpath = Pgm().LastVisitedLibraryPath( wxT( "doc" ) );
wxFileDialog FilesDialog( this, _( "Footprint document file:" ), docpath,
wxEmptyString, PdfFileWildcard,
wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );
if( FilesDialog.ShowModal() != wxID_OK )
return;
FullFileName = FilesDialog.GetPath();
/* If the path is already in the library search paths
* list, just add the library name to the list. Otherwise, add
* the library name with the full or relative path.
* the relative path, when possible is preferable,
* because it preserve use of default libraries paths, when the path is
* a sub path of these default paths
*/
wxFileName fn = FullFileName;
Pgm().SaveLastVisitedLibraryPath( fn.GetPath() );
filename = Pgm().FilenameWithRelativePathInSearchList( FullFileName );
m_TextHelpModulesFileName->SetValue( filename );
}
/////////////////////////////////////////////////////////////////////////////
// Name: dialog_display_options.h
// Author: jean-pierre Charras
// Licence: GPL
/////////////////////////////////////////////////////////////////////////////
#ifndef _DIALOG_CVPCB_CONFIG_H_
#define _DIALOG_CVPCB_CONFIG_H_
#include <dialog_cvpcb_config_fbp.h>
class DIALOG_CVPCB_CONFIG : public DIALOG_CVPCB_CONFIG_FBP
{
private:
CVPCB_MAINFRAME* m_Parent;
wxConfigBase* m_Config;
wxString m_UserLibDirBufferImg;
bool m_LibListChanged;
bool m_LibPathChanged;
private:
void Init();
// Virtual event handlers
void OnCloseWindow( wxCloseEvent& event );
void OnOkClick( wxCommandEvent& event );
void OnCancelClick( wxCommandEvent& event );
void OnAddOrInsertLibClick( wxCommandEvent& event );
void OnRemoveLibClick( wxCommandEvent& event );
void OnBrowseModDocFile( wxCommandEvent& event );
void OnAddOrInsertPath( wxCommandEvent& event );
void OnRemoveUserPath( wxCommandEvent& event );
void OnButtonUpClick( wxCommandEvent& event );
void OnButtonDownClick( wxCommandEvent& event );
public:
DIALOG_CVPCB_CONFIG( CVPCB_MAINFRAME* parent );
~DIALOG_CVPCB_CONFIG() {};
};
#endif
// _DIALOG_CVPCB_CONFIG_H_
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 10 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_cvpcb_config_fbp.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_CVPCB_CONFIG_FBP::DIALOG_CVPCB_CONFIG_FBP( 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( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbLibsChoiceSizer;
sbLibsChoiceSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Footprint library files") ), wxHORIZONTAL );
m_ListLibr = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_HSCROLL|wxLB_NEEDED_SB|wxLB_SINGLE );
m_ListLibr->SetToolTip( _("List of active library files.\nOnly library files in this list are loaded by Pcbnew.\nThe order of this list is important:\nPcbnew searchs for a given footprint using this list order priority.") );
m_ListLibr->SetMinSize( wxSize( 450,90 ) );
sbLibsChoiceSizer->Add( m_ListLibr, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerLibButtons;
bSizerLibButtons = new wxBoxSizer( wxVERTICAL );
m_buttonAddLib = new wxButton( this, ID_ADD_LIB, _("Add"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonAddLib->SetToolTip( _("Add a new library after the selected library, and load it") );
bSizerLibButtons->Add( m_buttonAddLib, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT, 5 );
m_buttonInsLib = new wxButton( this, ID_INSERT_LIB, _("Insert"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonInsLib->SetToolTip( _("Add a new library before the selected library, and load it") );
bSizerLibButtons->Add( m_buttonInsLib, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT, 5 );
m_buttonRemoveLib = new wxButton( this, ID_REMOVE_LIB, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonRemoveLib->SetToolTip( _("Unload the selected library") );
bSizerLibButtons->Add( m_buttonRemoveLib, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT, 5 );
m_buttonLibUp = new wxButton( this, ID_LIB_UP, _("Up"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerLibButtons->Add( m_buttonLibUp, 0, wxRIGHT|wxLEFT, 5 );
m_buttonLibDown = new wxButton( this, ID_LIB_DOWN, _("Down"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerLibButtons->Add( m_buttonLibDown, 0, wxRIGHT|wxLEFT, 5 );
sbLibsChoiceSizer->Add( bSizerLibButtons, 0, wxALIGN_CENTER_VERTICAL, 5 );
bMainSizer->Add( sbLibsChoiceSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxStaticBoxSizer* sbEquivChoiceSizer;
sbEquivChoiceSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Footprint alias files") ), wxHORIZONTAL );
m_ListEquiv = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_HSCROLL|wxLB_NEEDED_SB|wxLB_SINGLE );
m_ListEquiv->SetToolTip( _("List of active library files.\nOnly library files in this list are loaded by Pcbnew.\nThe order of this list is important:\nPcbnew searchs for a given footprint using this list order priority.") );
m_ListEquiv->SetMinSize( wxSize( 400,-1 ) );
sbEquivChoiceSizer->Add( m_ListEquiv, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerEquButtons;
bSizerEquButtons = new wxBoxSizer( wxVERTICAL );
m_buttonAddEqu = new wxButton( this, ID_ADD_EQU, _("Add"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonAddEqu->SetToolTip( _("Add a new library after the selected library, and load it") );
bSizerEquButtons->Add( m_buttonAddEqu, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 );
m_buttonInsEqu = new wxButton( this, ID_INSERT_EQU, _("Insert"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonInsEqu->SetToolTip( _("Add a new library before the selected library, and load it") );
bSizerEquButtons->Add( m_buttonInsEqu, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT, 5 );
m_buttonRemoveEqu = new wxButton( this, ID_REMOVE_EQU, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonRemoveEqu->SetToolTip( _("Unload the selected library") );
bSizerEquButtons->Add( m_buttonRemoveEqu, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 );
m_buttonEquUp = new wxButton( this, ID_EQU_UP, _("Up"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerEquButtons->Add( m_buttonEquUp, 0, wxRIGHT|wxLEFT, 5 );
m_buttonEquDown = new wxButton( this, ID_EQU_DOWN, _("Down"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerEquButtons->Add( m_buttonEquDown, 0, wxRIGHT|wxLEFT, 5 );
sbEquivChoiceSizer->Add( bSizerEquButtons, 0, wxALIGN_CENTER_VERTICAL, 5 );
bMainSizer->Add( sbEquivChoiceSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxStaticBoxSizer* sbModulesDocSizer;
sbModulesDocSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Footprint documentation file") ), wxHORIZONTAL );
m_TextHelpModulesFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
sbModulesDocSizer->Add( m_TextHelpModulesFileName, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_buttonModDoc = new wxButton( this, ID_BROWSE_MOD_DOC, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 );
sbModulesDocSizer->Add( m_buttonModDoc, 0, wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( sbModulesDocSizer, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxStaticBoxSizer* sbSizer4;
sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("User defined search paths") ), wxHORIZONTAL );
wxBoxSizer* bUserListSizer;
bUserListSizer = new wxBoxSizer( wxVERTICAL );
m_listUserPaths = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB );
m_listUserPaths->SetToolTip( _("Additional paths used in this project. The priority is higher than default KiCad paths.") );
m_listUserPaths->SetMinSize( wxSize( -1,70 ) );
bUserListSizer->Add( m_listUserPaths, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
sbSizer4->Add( bUserListSizer, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
wxBoxSizer* bUserPathsButtonsSizer;
bUserPathsButtonsSizer = new wxBoxSizer( wxVERTICAL );
m_buttonAddPath = new wxButton( this, ID_LIB_PATH_SEL, _("Add"), wxDefaultPosition, wxDefaultSize, 0 );
bUserPathsButtonsSizer->Add( m_buttonAddPath, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_buttonInsPath = new wxButton( this, ID_INSERT_PATH, _("Insert"), wxDefaultPosition, wxDefaultSize, 0 );
bUserPathsButtonsSizer->Add( m_buttonInsPath, 0, wxRIGHT|wxLEFT, 5 );
m_buttonRemovePath = new wxButton( this, ID_REMOVE_PATH, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 );
bUserPathsButtonsSizer->Add( m_buttonRemovePath, 0, wxRIGHT|wxLEFT, 5 );
sbSizer4->Add( bUserPathsButtonsSizer, 0, wxALIGN_CENTER_VERTICAL, 5 );
bMainSizer->Add( sbSizer4, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxStaticBoxSizer* sbSizer6;
sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Current search path list") ), wxHORIZONTAL );
m_DefaultLibraryPathslistBox = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB );
m_DefaultLibraryPathslistBox->SetToolTip( _("System and user paths used to search and load library files and component doc files.\nSorted by decreasing priority order.") );
m_DefaultLibraryPathslistBox->SetMinSize( wxSize( -1,70 ) );
sbSizer6->Add( m_DefaultLibraryPathslistBox, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( sbSizer6, 1, wxALL|wxEXPAND, 5 );
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bMainSizer->Add( m_staticline2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_sdbSizer2 = new wxStdDialogButtonSizer();
m_sdbSizer2OK = new wxButton( this, wxID_OK );
m_sdbSizer2->AddButton( m_sdbSizer2OK );
m_sdbSizer2Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer2->AddButton( m_sdbSizer2Cancel );
m_sdbSizer2->Realize();
bMainSizer->Add( m_sdbSizer2, 0, wxALL|wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnCloseWindow ) );
m_buttonAddLib->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonInsLib->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonRemoveLib->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnRemoveLibClick ), NULL, this );
m_buttonLibUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonUpClick ), NULL, this );
m_buttonLibDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonDownClick ), NULL, this );
m_buttonAddEqu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonInsEqu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonRemoveEqu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnRemoveLibClick ), NULL, this );
m_buttonEquUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonUpClick ), NULL, this );
m_buttonEquDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonDownClick ), NULL, this );
m_buttonModDoc->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnBrowseModDocFile ), NULL, this );
m_buttonAddPath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertPath ), NULL, this );
m_buttonInsPath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertPath ), NULL, this );
m_buttonRemovePath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnRemoveUserPath ), NULL, this );
m_sdbSizer2Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnCancelClick ), NULL, this );
m_sdbSizer2OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnOkClick ), NULL, this );
}
DIALOG_CVPCB_CONFIG_FBP::~DIALOG_CVPCB_CONFIG_FBP()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnCloseWindow ) );
m_buttonAddLib->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonInsLib->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonRemoveLib->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnRemoveLibClick ), NULL, this );
m_buttonLibUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonUpClick ), NULL, this );
m_buttonLibDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonDownClick ), NULL, this );
m_buttonAddEqu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonInsEqu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertLibClick ), NULL, this );
m_buttonRemoveEqu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnRemoveLibClick ), NULL, this );
m_buttonEquUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonUpClick ), NULL, this );
m_buttonEquDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnButtonDownClick ), NULL, this );
m_buttonModDoc->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnBrowseModDocFile ), NULL, this );
m_buttonAddPath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertPath ), NULL, this );
m_buttonInsPath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnAddOrInsertPath ), NULL, this );
m_buttonRemovePath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnRemoveUserPath ), NULL, this );
m_sdbSizer2Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnCancelClick ), NULL, this );
m_sdbSizer2OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CVPCB_CONFIG_FBP::OnOkClick ), NULL, this );
}
......@@ -95,11 +95,11 @@ void CVPCB_MAINFRAME::ReCreateMenuBar()
// Save the .cmp file
AddMenuItem( filesMenu, wxID_SAVE,
_( "&Save\tCtrl+S" ), SAVE_HLP_MSG, KiBitmap( save_xpm ) );
_( "&Save Cmp File\tCtrl+S" ), SAVE_HLP_MSG, KiBitmap( save_xpm ) );
// Save as the .cmp file
AddMenuItem( filesMenu, wxID_SAVEAS,
_( "Save &As...\tCtrl+Shift+S" ), SAVE_AS_HLP_MSG, KiBitmap( save_xpm ) );
_( "Save Cmp File &As...\tCtrl+Shift+S" ), SAVE_AS_HLP_MSG, KiBitmap( save_xpm ) );
// Separator
filesMenu->AppendSeparator();
......@@ -116,6 +116,12 @@ void CVPCB_MAINFRAME::ReCreateMenuBar()
_( "Edit Li&brary Table" ), _( "Setup footprint libraries" ),
KiBitmap( library_table_xpm ) );
AddMenuItem( preferencesMenu, ID_CVPCB_EQUFILES_LIST_EDIT,
_( "Edit &Equ Files List" ),
_( "Setup equ files list (.equ files)\n"
"They are files which give the footprint name from the component value"),
KiBitmap( library_table_xpm ) );
// Language submenu
Pgm().AddMenuLanguageList( preferencesMenu );
......@@ -134,11 +140,6 @@ void CVPCB_MAINFRAME::ReCreateMenuBar()
_( "Save changes to the project configuration file" ),
KiBitmap( save_setup_xpm ) );
AddMenuItem( preferencesMenu, ID_SAVE_PROJECT_AS,
_( "&Save Project File As" ),
_( "Save changes to a new project configuration file" ),
KiBitmap( save_setup_xpm ) );
// Menu Help:
wxMenu* helpMenu = new wxMenu;
......
......@@ -5,7 +5,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
*
......@@ -385,8 +385,9 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName )
}
else
{
wxFileDialog dlg( this, _( "Save Component Footprint Link File" ), wxEmptyString,
_( "Unnamed file" ), ComponentFileWildcard, wxFD_SAVE );
wxFileDialog dlg( this, _( "Save Component Footprint Link File" ),
Prj().GetProjectPath(),
wxT( "noname" ), ComponentFileWildcard, wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL )
return -1;
......@@ -395,47 +396,13 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName )
if( !fn.HasExt() )
fn.SetExt( ComponentFileExtension );
#if 0 // RHH 6-Jul-14: We did not auto generate the
// footprint table. And the dialog which does suppport editing does the saving.
// Besides, this is not the place to do this, it belies the name of this
// function.
// Save the project specific footprint library table.
if( !Prj().PcbFootprintLibs()->IsEmpty( false ) )
{
wxString fp_lib_tbl = Prj().FootprintLibTblName();
if( wxFileName::FileExists( fp_lib_tbl )
&& IsOK( this, _( "A footprint library table already exists in this path.\n\nDo "
"you want to overwrite it?" ) ) )
{
try
{
Prj().PcbFootprintLibs()->Save( fp_lib_tbl );
}
catch( const IO_ERROR& ioe )
{
wxString msg = wxString::Format( _(
"An error occurred attempting to save the "
"footprint library table '%s'\n\n%s" ),
GetChars( fp_lib_tbl ),
GetChars( ioe.errorText )
);
DisplayError( this, msg );
}
}
}
#endif
}
if( !IsWritable( fn.GetFullPath() ) )
return 0;
if( WriteComponentLinkFile( fn.GetFullPath() ) == 0 )
if( !IsWritable( fn.GetFullPath() ) || WriteComponentLinkFile( fn.GetFullPath() ) == 0 )
{
DisplayError( this, _( "Unable to create component footprint link file (.cmp)" ) );
DisplayError( this,
wxString::Format( _( "Unable to create component footprint link file '%s'" ),
fn.GetFullPath() ) );
return 0;
}
......
......@@ -69,10 +69,6 @@ void CVPCB_MAINFRAME::ReCreateHToolbar()
KiBitmap( show_footprint_xpm ),
_( "View selected footprint" ) );
m_mainToolBar->AddTool( ID_CVPCB_AUTO_ASSOCIE, wxEmptyString,
KiBitmap( auto_associe_xpm ),
_( "Perform automatic footprint association" ) );
m_mainToolBar->AddSeparator();
m_mainToolBar->AddTool( ID_CVPCB_GOTO_PREVIOUSNA, wxEmptyString,
KiBitmap( left_xpm ),
......@@ -83,6 +79,10 @@ void CVPCB_MAINFRAME::ReCreateHToolbar()
_( "Select next unlinked component" ) );
m_mainToolBar->AddSeparator();
m_mainToolBar->AddTool( ID_CVPCB_AUTO_ASSOCIE, wxEmptyString,
KiBitmap( auto_associe_xpm ),
_( "Perform automatic footprint association" ) );
m_mainToolBar->AddTool( ID_CVPCB_DEL_ASSOCIATIONS, wxEmptyString,
KiBitmap( delete_association_xpm ),
_( "Delete all associations (links)" ) );
......@@ -92,7 +92,6 @@ void CVPCB_MAINFRAME::ReCreateHToolbar()
KiBitmap( datasheet_xpm ),
_( "Display footprint documentation" ) );
m_mainToolBar->AddSeparator();
m_mainToolBar->AddSeparator();
m_mainToolBar->AddTool( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST,
KiBitmap( module_filtered_list_xpm ),
......
......@@ -62,6 +62,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
char line[1024];
strncpy( line, cmdline, sizeof(line) - 1 );
line[ sizeof(line) - 1 ] = '\0';
char* idcmd = strtok( line, " \n\r" );
char* text = strtok( NULL, "\"\n\r" );
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2013-2015 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 2013-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
......@@ -342,6 +342,7 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
// Add custom panels:
InstallCustomPages();
SetDefaultItem( m_buttonNetlist );
GetSizer()->SetSizeHints( this );
Centre();
......
......@@ -335,7 +335,7 @@ bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile )
default_path = search->LastVisitedPath();
wxFileDialog dlg( this, _( "Part Library Name:" ), default_path,
wxEmptyString, SchematicLibraryFileExtension,
wxEmptyString, SchematicLibraryFileWildcard,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
if( dlg.ShowModal() == wxID_CANCEL )
......
......@@ -668,19 +668,18 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter )
if( m_MultilineAllowed )
{
std::vector<wxPoint> positions;
wxArrayString* list = wxStringSplit( GetShownText(), '\n' );
positions.reserve( list->Count() );
wxArrayString strings_list;
wxStringSplit( GetShownText(), strings_list, '\n' );
positions.reserve( strings_list.Count() );
GetPositionsOfLinesOfMultilineText(positions, list->Count() );
GetPositionsOfLinesOfMultilineText(positions, strings_list.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
wxString& txt = list->Item( ii );
wxString& txt = strings_list.Item( ii );
aPlotter->Text( positions[ii], color, txt, m_Orient, m_Size, m_HJustify,
m_VJustify, thickness, m_Italic, m_Bold );
}
delete (list);
}
else
{
......
......@@ -339,11 +339,11 @@ double RoundTo0( double x, double precision );
/**
* Function wxStringSplit
* splits \a aString to a string list separated at \a aSplitter.
* @return the list
* @param aString is the text to split
* @param aText is the text to split
* @param aStrings will contain the splitted lines
* @param aSplitter is the 'split' character
*/
wxArrayString* wxStringSplit( wxString aString, wxChar aSplitter );
void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter );
/**
* Function GetRunningMicroSecs
......
......@@ -47,7 +47,7 @@
#define GROUP_SCH_LIBS wxT( "/eeschema/libraries" ) /// library list section
#define GROUP_CVP wxT("/cvpcb")
#define GROUP_CVP_EQU wxT("/cvpcb/libraries")
#define GROUP_CVP_EQU wxT("/cvpcb/equfiles")
#define CONFIG_VERSION 1
......
......@@ -247,7 +247,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
m_panelRegulators->SetSizer( bSizerMainReg );
m_panelRegulators->Layout();
bSizerMainReg->Fit( m_panelRegulators );
m_Notebook->AddPage( m_panelRegulators, _("Regulators"), true );
m_Notebook->AddPage( m_panelRegulators, _("Regulators"), false );
m_panelTrackWidth = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerTrackWidth;
bSizerTrackWidth = new wxBoxSizer( wxHORIZONTAL );
......@@ -593,7 +593,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
wxBoxSizer* bLeftSizer;
bLeftSizer = new wxBoxSizer( wxVERTICAL );
wxString m_TranslineSelectionChoices[] = { _("Microstrip Line"), _("Coplanar wave guide"), _("Grounded Coplanar wave guide"), _("Rectangular Waveguide"), _("Coaxial Line"), _("Coupled Microstrip Line"), _("Stripline"), _("Twisted Pair") };
wxString m_TranslineSelectionChoices[] = { _("Microstrip Line"), _("Coplanar wave guide"), _("Coplanar wave guide with ground plane"), _("Rectangular Waveguide"), _("Coaxial Line"), _("Coupled Microstrip Line"), _("Stripline"), _("Twisted Pair") };
int m_TranslineSelectionNChoices = sizeof( m_TranslineSelectionChoices ) / sizeof( wxString );
m_TranslineSelection = new wxRadioBox( m_panelTransline, wxID_ANY, _("Transmission Line Type:"), wxDefaultPosition, wxDefaultSize, m_TranslineSelectionNChoices, m_TranslineSelectionChoices, 1, wxRA_SPECIFY_COLS );
m_TranslineSelection->SetSelection( 0 );
......@@ -998,7 +998,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
m_panelTransline->SetSizer( bSizeTransline );
m_panelTransline->Layout();
bSizeTransline->Fit( m_panelTransline );
m_Notebook->AddPage( m_panelTransline, _("TransLine"), false );
m_Notebook->AddPage( m_panelTransline, _("TransLine"), true );
m_panelAttenuators = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxStaticBoxSizer* sbSizerAtt;
sbSizerAtt = new wxStaticBoxSizer( new wxStaticBox( m_panelAttenuators, wxID_ANY, _("label") ), wxHORIZONTAL );
......
......@@ -270,7 +270,7 @@
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Regulators</property>
<property name="select">1</property>
<property name="select">0</property>
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
......@@ -8181,7 +8181,7 @@
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">TransLine</property>
<property name="select">0</property>
<property name="select">1</property>
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
......@@ -8288,7 +8288,7 @@
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;Microstrip Line&quot; &quot;Coplanar wave guide&quot; &quot;Grounded Coplanar wave guide&quot; &quot;Rectangular Waveguide&quot; &quot;Coaxial Line&quot; &quot;Coupled Microstrip Line&quot; &quot;Stripline&quot; &quot;Twisted Pair&quot;</property>
<property name="choices">&quot;Microstrip Line&quot; &quot;Coplanar wave guide&quot; &quot;Coplanar wave guide with ground plane&quot; &quot;Rectangular Waveguide&quot; &quot;Coaxial Line&quot; &quot;Coupled Microstrip Line&quot; &quot;Stripline&quot; &quot;Twisted Pair&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
......@@ -403,22 +403,21 @@ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet(
if( IsMultilineAllowed() )
{
wxArrayString* list = wxStringSplit( GetShownText(), '\n' );
wxArrayString strings_list;
wxStringSplit( GetShownText(), strings_list, '\n' );
std::vector<wxPoint> positions;
positions.reserve( list->Count() );
GetPositionsOfLinesOfMultilineText( positions, list->Count() );
positions.reserve( strings_list.Count() );
GetPositionsOfLinesOfMultilineText( positions, strings_list.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
wxString txt = list->Item( ii );
wxString txt = strings_list.Item( ii );
DrawGraphicText( NULL, NULL, positions[ii], color,
txt, GetOrientation(), size,
GetHorizJustify(), GetVertJustify(),
GetThickness(), IsItalic(),
true, addTextSegmToPoly );
}
delete list;
}
else
{
......
......@@ -5,7 +5,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Cirilo Bernardo
* Copyright (C) 2013-2015 Cirilo Bernardo
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -46,15 +46,6 @@ private:
wxConfigBase* m_config;
bool m_idfThouOpt; // remember last preference for units in THOU
void OnCancelClick( wxCommandEvent& event )
{
EndModal( wxID_CANCEL );
}
void OnOkClick( wxCommandEvent& event )
{
EndModal( wxID_OK );
}
public:
DIALOG_EXPORT_IDF3( PCB_EDIT_FRAME* parent ) :
DIALOG_EXPORT_IDF3_BASE( parent )
......@@ -66,6 +57,11 @@ public:
m_config->Read( OPTKEY_IDF_THOU, &m_idfThouOpt );
m_rbUnitSelection->SetSelection( m_idfThouOpt ? 1 : 0 );
wxWindow* button = FindWindowByLabel( wxT( "OK" ) );
if( button )
SetDefaultItem( button );
GetSizer()->SetSizeHints( this );
Centre();
}
......@@ -112,9 +108,9 @@ void PCB_EDIT_FRAME::ExportToIDF3( wxCommandEvent& event )
wxString fullFilename = dlg.FilePicker()->GetPath();
if ( !Export_IDF3( GetBoard(), fullFilename, thou ) )
if( !Export_IDF3( GetBoard(), fullFilename, thou ) )
{
wxString msg = _("Unable to create ") + fullFilename;
wxString msg = _( "Unable to create " ) + fullFilename;
wxMessageBox( msg );
return;
}
......
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Nov 6 2013)
// C++ code generated with wxFormBuilder (version Jun 5 2014)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
......@@ -16,20 +16,22 @@ DIALOG_EXPORT_IDF3_BASE::DIALOG_EXPORT_IDF3_BASE( wxWindow* parent, wxWindowID i
wxBoxSizer* bSizerIDFFile;
bSizerIDFFile = new wxBoxSizer( wxVERTICAL );
bSizerIDFFile->SetMinSize( wxSize( 500,-1 ) );
m_txtBrdFile = new wxStaticText( this, wxID_ANY, _("IDF board file"), wxDefaultPosition, wxDefaultSize, 0 );
m_txtBrdFile = new wxStaticText( this, wxID_ANY, _("File name:"), wxDefaultPosition, wxDefaultSize, 0 );
m_txtBrdFile->Wrap( -1 );
bSizerIDFFile->Add( m_txtBrdFile, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
bSizerIDFFile->Add( m_txtBrdFile, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxTOP, 5 );
m_filePickerIDF = new wxFilePickerCtrl( this, wxID_ANY, wxEmptyString, _("Select an IDF export filename"), wxT("*.emn"), wxDefaultPosition, wxSize( 450,-1 ), wxFLP_OVERWRITE_PROMPT|wxFLP_SAVE|wxFLP_USE_TEXTCTRL );
bSizerIDFFile->Add( m_filePickerIDF, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
wxString m_rbUnitSelectionChoices[] = { _("Millimeters"), _("Mils") };
int m_rbUnitSelectionNChoices = sizeof( m_rbUnitSelectionChoices ) / sizeof( wxString );
m_rbUnitSelection = new wxRadioBox( this, wxID_ANY, _("IDF File Units"), wxDefaultPosition, wxDefaultSize, m_rbUnitSelectionNChoices, m_rbUnitSelectionChoices, 1, wxRA_SPECIFY_COLS );
m_rbUnitSelection = new wxRadioBox( this, wxID_ANY, _("Units"), wxDefaultPosition, wxDefaultSize, m_rbUnitSelectionNChoices, m_rbUnitSelectionChoices, 1, wxRA_SPECIFY_COLS );
m_rbUnitSelection->SetSelection( 0 );
bSizerIDFFile->Add( m_rbUnitSelection, 0, wxALL, 5 );
bSizerIDFFile->Add( 0, 0, 1, 0, 5 );
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerIDFFile->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
......@@ -40,11 +42,12 @@ DIALOG_EXPORT_IDF3_BASE::DIALOG_EXPORT_IDF3_BASE( wxWindow* parent, wxWindowID i
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
bSizerIDFFile->Add( m_sdbSizer1, 0, wxALIGN_RIGHT, 5 );
bSizerIDFFile->Add( m_sdbSizer1, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
this->SetSizer( bSizerIDFFile );
this->Layout();
bSizerIDFFile->Fit( this );
this->Centre( wxBOTH );
}
......
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="11" />
<FileVersion major="1" minor="13" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
......@@ -44,7 +44,7 @@
<property name="minimum_size"></property>
<property name="name">DIALOG_EXPORT_IDF3_BASE</property>
<property name="pos"></property>
<property name="size">424,191</property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Export IDFv3</property>
......@@ -89,13 +89,13 @@
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size">500,-1</property>
<property name="minimum_size">-1,-1</property>
<property name="name">bSizerIDFFile</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT|wxTOP</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
......@@ -125,7 +125,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">IDF board file</property>
<property name="label">File name:</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
......@@ -298,7 +298,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">IDF File Units</property>
<property name="label">Units</property>
<property name="majorDimension">1</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
......@@ -355,6 +355,16 @@
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag"></property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
......@@ -438,7 +448,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_RIGHT</property>
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">0</property>
......
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Nov 6 2013)
// C++ code generated with wxFormBuilder (version Jun 5 2014)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
......@@ -47,7 +47,7 @@ class DIALOG_EXPORT_IDF3_BASE : public DIALOG_SHIM
public:
DIALOG_EXPORT_IDF3_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export IDFv3"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 424,191 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
DIALOG_EXPORT_IDF3_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export IDFv3"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_EXPORT_IDF3_BASE();
};
......
......@@ -5,8 +5,8 @@
/*
* 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) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* 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
......@@ -49,10 +49,13 @@
#include <wx/wx.h>
#include <wx/url.h>
#include <wx/progdlg.h>
#include <pgm_base.h>
#include <kiface_i.h>
#include <dialog_helpers.h>
#include <project.h> // For PROJECT_VAR_NAME definition
#include <fp_lib_table.h> // For KISYSMOD definition
#include <io_mgr.h>
#include <wizard_add_fplib.h>
#include <dialog_select_dirlist_base.h>
......@@ -88,6 +91,9 @@ WIZARD_FPLIB_TABLE::WIZARD_FPLIB_TABLE( wxWindow* aParent, wxArrayString& aEnvVa
m_buttonAddEV->Show( false );
m_buttonRemoveEV->Show( false );
#ifndef BUILD_GITHUB_PLUGIN
m_buttonGithubLibList->Show( false );
#endif
// Gives a minimal size to the dialog, which allows displaying any page
wxSize minsize;
......@@ -130,14 +136,18 @@ void WIZARD_FPLIB_TABLE::initDlg( wxArrayString& aEnvVariableList )
wxString msg;
wxConfigBase* cfg = Pgm().CommonSettings();
cfg->Read( KICAD_FPLIBS_URL_KEY, &msg );
cfg->Read( WIZARD_LAST_PLUGIN_KEY, &m_last_plugin_choice );
cfg->Read( WIZARD_LAST_PATHOPTION_KEY, &m_last_defaultpath_choice );
cfg->Read( KICAD_FPLIBS_URL_KEY, &msg );
if( msg.IsEmpty() )
m_textCtrlGithubURL->SetValue( wxT( "http://github.com/KiCad/" ) );
else
m_textCtrlGithubURL->SetValue( msg );
if( msg.IsEmpty() ) // Give our current KiCad github URL
msg = wxT( "http://github.com/KiCad" );
// Be sure there is no trailing '/' at the end of the repo name
if( msg.EndsWith( wxT("/" ) ) )
msg.RemoveLast();
m_textCtrlGithubURL->SetValue( msg );
// KIGITHUB is frequently used (examples in docs, and other place)
// So add it if it not yet in list, but if it is defined as env var
......@@ -211,7 +221,7 @@ bool WIZARD_FPLIB_TABLE::ValidateOptions()
// Warn the user when this is the case
wxString msg;
if( GetSelectedEnvVarValue().IsEmpty() )
if( getSelectedEnvVarValue().IsEmpty() )
{
// PROJECT_PATH option cannot be used with empty local path
if( m_rbPathManagement->GetSelection() == PROJECT_PATH )
......@@ -225,7 +235,7 @@ bool WIZARD_FPLIB_TABLE::ValidateOptions()
{
wxMessageBox( wxString::Format(
_("The default path defined by env var \"%s\" is empty.\nCannot use it"),
GetChars( GetSelectedEnvVar() ) ) );
GetChars( getSelectedEnvVar() ) ) );
return false;
}
}
......@@ -234,7 +244,7 @@ bool WIZARD_FPLIB_TABLE::ValidateOptions()
if( IsGithubPlugin() )
{
// Github plugin cannot be used with local path; Need absolute path or valid URL
if( !GetSelectedEnvVarValue().Lower().StartsWith( "http" ) )
if( !getSelectedEnvVarValue().Lower().StartsWith( "http" ) )
{
msg = _("Github Plugin uses a valid Internet URL starting by http.\n"
"Cannot be used as URL");
......@@ -244,7 +254,7 @@ bool WIZARD_FPLIB_TABLE::ValidateOptions()
}
else
{
if( GetSelectedEnvVarValue().Lower().StartsWith( "http" ) )
if( getSelectedEnvVarValue().Lower().StartsWith( "http" ) )
{
msg = _("This default path looks strange.\n"
"Cannot be used for a file path");
......@@ -267,6 +277,10 @@ void WIZARD_FPLIB_TABLE::OnPluginSelection( wxCommandEvent& event )
void WIZARD_FPLIB_TABLE::updateFromPlugingChoice()
{
#ifdef BUILD_GITHUB_PLUGIN
m_buttonGithubLibList->Show( IsGithubPlugin() || IsKicadPlugin() );
#endif
// update dialog options and widgets depending on a plugin choice
// Project path has no sense for GITHUB_PLUGIN
bool enablePrjPathOpt = not IsGithubPlugin();
......@@ -293,7 +307,7 @@ void WIZARD_FPLIB_TABLE::updateFromPlugingChoice()
{
if( first_github_envvar < 0 )
force_absolute_path = true;
else if( !GetSelectedEnvVarValue().StartsWith( "http" ) )
else if( !getSelectedEnvVarValue().StartsWith( "http" ) )
m_gridEnvironmentVariablesList->SelectRow( first_github_envvar );
}
......@@ -378,7 +392,7 @@ void WIZARD_FPLIB_TABLE::OnSelectEnvVarCell( wxGridEvent& event )
m_gridEnvironmentVariablesList->SelectRow( event.GetRow() );
}
wxString WIZARD_FPLIB_TABLE::GetSelectedEnvVar()
wxString WIZARD_FPLIB_TABLE::getSelectedEnvVar()
{
wxString envVar;
wxArrayInt selectedRows = m_gridEnvironmentVariablesList->GetSelectedRows();
......@@ -405,7 +419,7 @@ wxString WIZARD_FPLIB_TABLE::GetSelectedEnvVar()
}
wxString WIZARD_FPLIB_TABLE::GetSelectedEnvVarValue()
wxString WIZARD_FPLIB_TABLE::getSelectedEnvVarValue()
{
wxString envVarValue;
wxArrayInt selectedRows = m_gridEnvironmentVariablesList->GetSelectedRows();
......@@ -454,7 +468,7 @@ void WIZARD_FPLIB_TABLE::OnPageChanging( wxWizardEvent& event )
if( ( m_rbPathManagement->GetSelection() != ABSOLUTE_PATH ) &&
( IsGithubPlugin() ) )
{
wxURI uri( GetSelectedEnvVarValue() );
wxURI uri( getSelectedEnvVarValue() );
// We cannot use wxURL to test the validity of the url, because
// wxURL does not know https protocol we are using, and aways returns
......@@ -465,7 +479,7 @@ void WIZARD_FPLIB_TABLE::OnPageChanging( wxWizardEvent& event )
{
wxMessageBox( wxString::Format(
_("The URL defined by env var \"%s\" is an incorrect URL.\nCannot use it"),
GetChars( GetSelectedEnvVar() ) ) );
GetChars( getSelectedEnvVar() ) ) );
event.Veto();
}
}
......@@ -484,10 +498,12 @@ bool WIZARD_FPLIB_TABLE::setSecondPage()
{
case 0: // Kicad lib type
m_currLibDescr = new LIB_DESCR_KICAD;
m_buttonGithubLibList->SetLabel( _("Download Github Libs") );
break;
case 1: // Github lib type
m_currLibDescr = new LIB_DESCR_GITHUB;
m_buttonGithubLibList->SetLabel( _("Github Libs List") );
break;
case 2: // Legacy lib type
......@@ -503,6 +519,17 @@ bool WIZARD_FPLIB_TABLE::setSecondPage()
break;
}
if( IsGithubPlugin() )
{
#ifdef KICAD_USE_WEBKIT
m_buttonAddLib->SetLabel( _("Add Libs with WebViewer") );
#else
m_buttonAddLib->SetLabel( _("Add FP Library entry") );
#endif
}
else
m_buttonAddLib->SetLabel( _("Add FP Libraries") );
return m_currLibDescr!= NULL;
}
......@@ -515,15 +542,15 @@ bool WIZARD_FPLIB_TABLE::setLastPage() // Init prms for the last wizard page
{
case ENV_VAR_PATH: // Choice = path relative env var
case PROJECT_PATH: // Choice = path relative to the project
m_currLibDescr->m_EnvVarName = GetSelectedEnvVar();
m_currLibDescr->m_DefaultPath = GetSelectedEnvVarValue();
m_currLibDescr->m_EnvVarName = getSelectedEnvVar();
m_currLibDescr->m_DefaultPath = getSelectedEnvVarValue();
m_currLibDescr->m_IsAbsolutePath = false;
m_textOption->SetLabel( wxString::Format( wxT("%s (%s)"),
m_rbPathManagement->GetStringSelection().GetData(),
GetSelectedEnvVar().GetData() ) );
getSelectedEnvVar().GetData() ) );
m_textPath->SetLabel( GetSelectedEnvVarValue() );
m_textPath->SetLabel( getSelectedEnvVarValue() );
break;
case ABSOLUTE_PATH: // Choice = absolute path
......@@ -548,7 +575,7 @@ void WIZARD_FPLIB_TABLE::OnAddFpLibs( wxCommandEvent& event )
if( m_currLibDescr->m_IsFile )
selectLibsFiles();
else if( m_currLibDescr->m_IsGitHub )
selectLibsGithub();
selectLibsGithubWithWebViewer();
else
selectLibsFolders();
......@@ -708,7 +735,7 @@ extern int RunWebViewer( wxWindow * aParent, const wxString& aUrlOnStart,
wxArrayString* aUrlListSelection = NULL );
#endif
void WIZARD_FPLIB_TABLE::selectLibsGithub() // select a set of library on Github
void WIZARD_FPLIB_TABLE::selectLibsGithubWithWebViewer() // select a set of library on Github
{
// A string array to store the URLs selected from the web viewer:
wxArrayString urls;
......@@ -722,16 +749,25 @@ void WIZARD_FPLIB_TABLE::selectLibsGithub() // select a set of library on Git
#ifdef KICAD_USE_WEBKIT
RunWebViewer( this, defaultURL, &urls );
#else
urls.Add( defaultURL + wxT("newlibname.pretty") );
// If the Web Viewer is not available, just add a template
// to the fp lib table.
// The user have to edit it
urls.Add( defaultURL + wxT("/newlibname.pretty") );
#endif
installGithubLibsFromList( urls );
}
void WIZARD_FPLIB_TABLE::installGithubLibsFromList( wxArrayString& aUrlList )
{
// add the libs found in aUrlList, after calculating a nickname and
// replacing the path by an env variable, if needed
// Create the nickname: currently make it from the url
wxArrayString filepaths;
wxArrayString nicknames;
for( unsigned ii = 0; ii < urls.GetCount(); ii++ )
for( unsigned ii = 0; ii < aUrlList.GetCount(); ii++ )
{
wxString urlstring( urls[ii] );
wxString urlstring( aUrlList[ii] );
wxURI uri( urlstring );
......@@ -746,19 +782,19 @@ void WIZARD_FPLIB_TABLE::selectLibsGithub() // select a set of library on Git
if( m_currLibDescr->m_IsAbsolutePath ||
m_currLibDescr->m_DefaultPath.IsEmpty() )
{
filepaths.Add( urls[ii] ); // use the full URL
filepaths.Add( aUrlList[ii] ); // use the full URL
}
else
{
wxString shortURI;
if( urls[ii].Lower().StartsWith(
if( aUrlList[ii].Lower().StartsWith(
m_currLibDescr->m_DefaultPath.Lower(), &shortURI ) )
{
shortURI.Prepend( wxT("${") + m_currLibDescr->m_EnvVarName + wxT("}") );
filepaths.Add( shortURI );
}
else // keep the full URL
filepaths.Add( urls[ii] ); // use the full URL
filepaths.Add( aUrlList[ii] ); // use the full URL
}
}
......@@ -784,3 +820,142 @@ void WIZARD_FPLIB_TABLE::OnRemoveFpLibs( wxCommandEvent& event )
m_gridFpListLibs->SelectRow( m_gridFpListLibs->GetGridCursorRow() );
}
#ifdef BUILD_GITHUB_PLUGIN
#include <../github/github_getliblist.h>
void WIZARD_FPLIB_TABLE::OnGithubLibsList( wxCommandEvent& event )
{
wxArrayString liblist;
getLibsListGithub( liblist );
if( liblist.GetCount() == 0 ) // No lib selected
return;
if( IsKicadPlugin() )
{
wxString msg;
if( !downloadGithubLibsFromList( liblist, &msg ) )
{
wxMessageBox( msg );
return;
}
}
else
installGithubLibsFromList( liblist );
}
void WIZARD_FPLIB_TABLE::getLibsListGithub( wxArrayString& aList )
{
wxBeginBusyCursor();
// Be sure there is no trailing '/' at the end of the repo name
wxString git_url = m_textCtrlGithubURL->GetValue();
if( git_url.EndsWith( wxT("/" ) ) )
{
git_url.RemoveLast();
m_textCtrlGithubURL->SetValue( git_url );
}
GITHUB_GETLIBLIST getter( git_url );
wxArrayString fullList;
getter.GetLibraryList( fullList );
wxEndBusyCursor();
wxArrayInt choices;
wxString msg( _( "Urls detected as footprint .pretty libraries.\n"
"Selected urls will be added to the current footprint library list" ) );
if( wxGetSelectedChoices( choices, msg,
_( "Footprint libraries" ), fullList, this ) <= 0 )
return;
// Add selected url in list
for( unsigned ii = 0; ii < choices.GetCount(); ii++ )
{
wxString& url = fullList[choices[ii]];
aList.Add( url );
}
}
// Download the .pretty libraries found in aUrlLis and store them on disk
// in a master folder
bool WIZARD_FPLIB_TABLE::downloadGithubLibsFromList( wxArrayString& aUrlList,
wxString * aErrorMessage )
{
wxString masterFolder;
wxString default_path;
wxGetEnv( FP_LIB_TABLE::GlobalPathEnvVariableName(), &default_path );
masterFolder = wxDirSelector( _("Output Folder" ),
default_path, 0, wxDefaultPosition, this );
if( masterFolder.IsEmpty() ) // Aborted by user
{
if( aErrorMessage )
*aErrorMessage = _( "Aborted" );
return false;
}
if( !wxDirExists( masterFolder ) )
{
if( aErrorMessage )
aErrorMessage->Printf( _( "Folder '%s' does not exists" ),
GetChars( masterFolder ) );
return false;
}
// Display a progress bar to show the downlaod state
wxProgressDialog pdlg( _("Download libraries"), wxEmptyString, aUrlList.GetCount() );
// Download libs:
for( unsigned ii = 0; ii < aUrlList.GetCount(); ii++ )
{
wxString& libsrc_name = aUrlList[ii];
wxString libdst_name;
// Extract the lib name from the full URL:
wxURI url( libsrc_name );
wxFileName fn( url.GetPath() );
// Set our local path
fn.SetPath( masterFolder );
libdst_name = fn.GetFullPath();
if( !wxDirExists( libdst_name ) )
wxMkdir( libdst_name );
pdlg.Update( ii, libsrc_name);
try
{
PLUGIN::RELEASER src( IO_MGR::PluginFind( IO_MGR::GITHUB ) );
PLUGIN::RELEASER dst( IO_MGR::PluginFind( IO_MGR::KICAD ) );
wxArrayString footprints = src->FootprintEnumerate( libsrc_name );
for( unsigned i = 0; i < footprints.size(); ++i )
{
std::auto_ptr<MODULE> m( src->FootprintLoad( libsrc_name, footprints[i] ) );
dst->FootprintSave( libdst_name, m.get() );
// m is deleted here by auto_ptr.
}
}
catch( const IO_ERROR& ioe )
{
if( aErrorMessage )
aErrorMessage->Printf( _("Error:\n'%s'\nwhile downloading library:\n'%s'"),
GetChars( ioe.errorText ), GetChars( libsrc_name ) );
return false;
}
}
return true;
}
#endif
......@@ -112,13 +112,38 @@ public:
private:
void initDlg( wxArrayString& aEnvVariableList );
wxString GetSelectedEnvVar(); // return the selected env variable
wxString GetSelectedEnvVarValue(); // return the selected env variable value
wxString getSelectedEnvVar(); // return the selected env variable
wxString getSelectedEnvVarValue(); // return the selected env variable value
bool setSecondPage(); // Init prms for the second wizard page
bool setLastPage(); // Init prms for the last wizard page
void selectLibsFiles(); // select a set of library files
void selectLibsFolders(); // select a set of library folders
void selectLibsGithub(); // select a set of library on Github
/** select a set of library on Github, using the Web viewer to explore
* the repos
*/
void selectLibsGithubWithWebViewer();
/** Get the list of .pretty libraries on Github,
* without using the viewer, from the lib list extracted from the KiCad repos
*/
void getLibsListGithub( wxArrayString& aList );
/** Helper function.
* add the .pretty libraries found in aUrlList, after calculating a nickname and
* replacing the path by an env variable, if allowed and possible
*/
void installGithubLibsFromList( wxArrayString& aUrlList );
/**
* Download the .pretty libraries found in aUrlLis and store them on disk
* in a master folder
* @return true if OK, false on error
* @param aUrlList is the list of Github .pretty libs to download
* @param aErrorMessage is a wxString pointer to store error messages if any.
*/
bool downloadGithubLibsFromList( wxArrayString& aUrlList, wxString * aErrorMessage = NULL );
void updateFromPlugingChoice(); // update dialog options and widgets
// depending on the plugin choice
int GetEnvVarCount() // Get the number of rows in env var table
......@@ -136,6 +161,12 @@ private:
return m_rbFpLibFormat->GetSelection() == GITHUB_PLUGIN;
}
bool IsKicadPlugin() // Helper funct, return true if
{ // the Kicad plugin is the choice
return m_rbFpLibFormat->GetSelection() == KICAD_PLUGIN;
}
int HasGithubEnvVarCompatible(); // Return the first index to one env var
// which defines a url compatible github
// or -1 if not found
......@@ -156,6 +187,9 @@ private:
void OnPathManagementSelection( wxCommandEvent& event );
void OnSelectEnvVarCell( wxGridEvent& event );
void OnPluginSelection( wxCommandEvent& event );
#ifdef BUILD_GITHUB_PLUGIN
void OnGithubLibsList( wxCommandEvent& event );
#endif
bool ValidateOptions();
};
......
......@@ -200,6 +200,9 @@ WIZARD_FPLIB_TABLE_BASE::WIZARD_FPLIB_TABLE_BASE( wxWindow* parent, wxWindowID i
wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxHORIZONTAL );
m_buttonGithubLibList = new wxButton( m_wizPage3, wxID_ANY, _("Github Libs List"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_buttonGithubLibList, 0, wxALL, 5 );
m_buttonAddLib = new wxButton( m_wizPage3, wxID_ANY, _("Add FP Libraries"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_buttonAddLib, 0, wxALL, 5 );
......@@ -231,6 +234,7 @@ WIZARD_FPLIB_TABLE_BASE::WIZARD_FPLIB_TABLE_BASE( wxWindow* parent, wxWindowID i
m_gridEnvironmentVariablesList->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( WIZARD_FPLIB_TABLE_BASE::OnSelectEnvVarCell ), NULL, this );
m_buttonAddEV->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnAddEVariable ), NULL, this );
m_buttonRemoveEV->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnRemoveEVariable ), NULL, this );
m_buttonGithubLibList->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnGithubLibsList ), NULL, this );
m_buttonAddLib->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnAddFpLibs ), NULL, this );
m_buttonRemoveLib->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnRemoveFpLibs ), NULL, this );
}
......@@ -246,6 +250,7 @@ WIZARD_FPLIB_TABLE_BASE::~WIZARD_FPLIB_TABLE_BASE()
m_gridEnvironmentVariablesList->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( WIZARD_FPLIB_TABLE_BASE::OnSelectEnvVarCell ), NULL, this );
m_buttonAddEV->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnAddEVariable ), NULL, this );
m_buttonRemoveEV->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnRemoveEVariable ), NULL, this );
m_buttonGithubLibList->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnGithubLibsList ), NULL, this );
m_buttonAddLib->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnAddFpLibs ), NULL, this );
m_buttonRemoveLib->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WIZARD_FPLIB_TABLE_BASE::OnRemoveFpLibs ), NULL, this );
......
......@@ -1942,6 +1942,94 @@
<property name="name">bSizer5</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</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">Github Libs List</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_buttonGithubLibList</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="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">OnGithubLibsList</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">wxALL</property>
......
......@@ -61,6 +61,7 @@ class WIZARD_FPLIB_TABLE_BASE : public wxWizard
wxStaticText* m_textPath;
wxStaticText* m_staticText2;
wxGrid* m_gridFpListLibs;
wxButton* m_buttonGithubLibList;
wxButton* m_buttonAddLib;
wxButton* m_buttonRemoveLib;
......@@ -73,6 +74,7 @@ class WIZARD_FPLIB_TABLE_BASE : public wxWizard
virtual void OnSelectEnvVarCell( wxGridEvent& event ) { event.Skip(); }
virtual void OnAddEVariable( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemoveEVariable( wxCommandEvent& event ) { event.Skip(); }
virtual void OnGithubLibsList( wxCommandEvent& event ) { event.Skip(); }
virtual void OnAddFpLibs( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemoveFpLibs( wxCommandEvent& event ) { event.Skip(); }
......
......@@ -378,7 +378,7 @@ static void idf_export_module( BOARD* aPcb, MODULE* aModule,
IDF3_COMP_OUTLINE* outline;
outline = aIDFBoard.GetComponentOutline( modfile->GetShape3DName() );
outline = aIDFBoard.GetComponentOutline( modfile->GetShape3DFullFilename() );
if( !outline )
throw( std::runtime_error( aIDFBoard.GetError() ) );
......
......@@ -635,14 +635,15 @@ static void export_vrml_pcbtext( MODEL_VRML& aModel, TEXTE_PCB* text )
if( text->IsMultilineAllowed() )
{
wxArrayString* list = wxStringSplit( text->GetShownText(), '\n' );
wxArrayString strings_list;
wxStringSplit( text->GetShownText(), strings_list, '\n' );
std::vector<wxPoint> positions;
positions.reserve( list->Count() );
text->GetPositionsOfLinesOfMultilineText( positions, list->Count() );
positions.reserve( strings_list.Count() );
text->GetPositionsOfLinesOfMultilineText( positions, strings_list.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
wxString txt = list->Item( ii );
wxString& txt = strings_list.Item( ii );
DrawGraphicText( NULL, NULL, positions[ii], color,
txt, text->GetOrientation(), size,
text->GetHorizJustify(), text->GetVertJustify(),
......@@ -650,8 +651,6 @@ static void export_vrml_pcbtext( MODEL_VRML& aModel, TEXTE_PCB* text )
true,
vrml_text_callback );
}
delete (list);
}
else
{
......
......@@ -51,7 +51,7 @@ set( CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-sign-compare -Wno-reorder -Wno-unused-variable -Wno-unused-function -Wno-strict-aliasing" )
set( GITHUB_PLUGIN_SRCS
github_plugin.cpp
github_plugin.cpp github_getliblist.cpp
)
add_library( github_plugin STATIC ${GITHUB_PLUGIN_SRCS} )
......
/*
* 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 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
* 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
*/
/*
* While creating a wizard to edit the fp lib tables, and mainly the web viewer
* which can read the list of pretty library on a github repos, I was told there is
* this URL to retrieve info from any particular repo:
*
* https://api.github.com/orgs/KiCad/repos
* or
* https://api.github.com/users/KiCad/repos
*
* This gets just information on the repo in JSON format.
*
* I used avhttp, already used in the pcbnew Github plugin to download
* the json file.
*
* JP Charras.
*/
#if 0
/*
* FIX ME
* I do not include avhttp.hpp here, because it is already included in
* github_plugin.cpp
* and if it is also included in this file, the link fails (double definiton of modules)
* therefore, the GITHUB_GETLIBLIST method which uses avhttp to download dats from gitub
* is in github_plugin.cpp
*/
#ifndef WIN32_LEAN_AND_MEAN
// when WIN32_LEAN_AND_MEAN is defined, some useless includes in <window.h>
// are skipped, and this avoid some compil issues
#define WIN32_LEAN_AND_MEAN
#endif
#ifdef WIN32
// defines needed by avhttp
// Minimal Windows version is XP: Google for _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
#endif
#include <wx/wx.h>
#include <avhttp.hpp>
#endif
#include <wx/uri.h>
#include <github_getliblist.h>
#include <macros.h>
#include <common.h>
GITHUB_GETLIBLIST::GITHUB_GETLIBLIST( const wxString& aRepoURL )
{
m_repoURL = aRepoURL;
}
bool GITHUB_GETLIBLIST::GetLibraryList( wxArrayString& aList )
{
std::string fullURLCommand;
int page = 1;
int itemCountMax = 99; // Do not use a valu > 100, it does not work
// Github max items returned is 100 per page
if( !repoURL2listURL( m_repoURL, &fullURLCommand, itemCountMax, page ) )
{
wxString msg = wxString::Format( _( "malformed URL:\n'%s'" ), GetChars( m_repoURL ) );
wxMessageBox( msg );
return false;
}
// The URL lib names are relative to the server name.
// so add the server name to them.
wxURI repo( m_repoURL );
wxString urlPrefix = wxT( "https://" ) + repo.GetServer() + wxT( "/" );;
wxString errorMsg;
const char sep = ','; // Separator fields, in json returned file
wxString tmp;
int items_count_per_page = 0;
while( 1 )
{
bool success = remote_get_json( &fullURLCommand, &errorMsg );
if( !success )
{
wxMessageBox( errorMsg );
return false;
}
for( unsigned ii = 0; ii < m_json_image.size(); ii++ )
{
if( m_json_image[ii] == sep || ii == m_json_image.size() - 1 )
{
if( tmp.StartsWith( wxT( "\"full_name\"" ) ) )
{
#define QUOTE '\"'
// Remove useless quotes:
if( tmp[tmp.Length() - 1] == QUOTE )
tmp.RemoveLast();
if( tmp.EndsWith( wxT( ".pretty" ) ) )
{
aList.Add( tmp.AfterLast( ':' ) );
int idx = aList.GetCount() - 1;
if( aList[idx][0] == QUOTE )
aList[idx].Remove( 0, 1 );
aList[idx].Prepend( urlPrefix );
}
items_count_per_page++;
}
tmp.Clear();
}
else
tmp << m_json_image[ii];
}
if( items_count_per_page >= itemCountMax )
{
page++;
repoURL2listURL( m_repoURL, &fullURLCommand, itemCountMax, page );
items_count_per_page = 0;
m_json_image.clear();
}
else
break;
}
aList.Sort();
return true;
}
bool GITHUB_GETLIBLIST::repoURL2listURL( const wxString& aRepoURL,
std::string* aFullURLCommand,
int aItemCountMax, int aPage )
{
// aListURL is e.g. "https://api.github.com/orgs/KiCad/repos"
// or "https://api.github.com/users/KiCad/repos"
// aRepoURL is e.g. "https://github.com/KiCad"
// Github has a default pagination set to 30 items.
// but allows up to 100 items max if we add the "?per_page=100" option
wxURI repo( aRepoURL );
if( repo.HasServer() && repo.HasPath() )
{
// goal: "https://api.github.com/orgs/KiCad"
wxString target_url( wxT( "https://api.github.com/orgs" ) );
target_url += repo.GetPath();
target_url += wxT( "/repos" );
// Github has a default pagination set to 30 items.
// but allows up to 100 items max. Use this limit
target_url += wxString::Format( "?per_page=%d&page=%d", aItemCountMax, aPage );
*aFullURLCommand = target_url.utf8_str();
return true;
}
return false;
}
/*
* 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) 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 GITHUB_GETLIBLIST_H_
#define GITHUB_GETLIBLIST_H_
/**
* Class GITHUB_GETLIBLIST
* implements a portion of pcbnew's PLUGIN interface to provide read only access
* to a github repo to extract pretty footprints library list, in json format.
*
* this plugin simply reads in a zip file of the repo and unzips it from RAM as
* needed. Therefore this "Github" plugin is <b>read only for accessing remote
* at https://api.github.com/orgs/KiCad/repos</b>
*/
class GITHUB_GETLIBLIST
{
public:
// -----<API>----------------------------------------------------------
bool GetLibraryList( wxArrayString& aList );
// -----</API>---------------------------------------------------------
GITHUB_GETLIBLIST( const wxString& aRepoURL );
~GITHUB_GETLIBLIST() {}
protected:
/**
* Function repoURL2listURL
* translates a repo URL to the URL name which gives the state of repos URL
* as commonly seen on github.com
*
* @param aRepoURL points to the base of the repo.
* @param aFullURLCommand is URL the full URL command (URL+options).
* @param aItemCountMax is the max item count in apage,
* and is 100 for github repo.
* @param aPage is the page number, if there are more than one page in repo.
* @return bool - true if @a aRepoULR was parseable, else false
*/
bool repoURL2listURL( const wxString& aRepoURL, std::string* aFullURLCommand,
int aItemCountMax, int aPage = 1 );
/**
* Function remote_get_json
* Download a json text from a github repo. The text image
* is received into the m_input_stream.
* @param aFullURLCommand the full command, i.e. the url with options like
* "https://api.github.com/users/KiCad/repos?per_page=100?page=1"
* @param aMsgError a pointer to a wxString which can store an error message
* @return true if OK, false if error (which an error message in *aMsgError
*/
bool remote_get_json( std::string* aFullURLCommand, wxString* aMsgError );
wxString m_github_path; ///< Something like https://api.github.com/orgs/KiCad
std::string m_json_image; ///< image of the text file in its entirety.
wxString m_repoURL; // the URL of the Github repo
};
#endif // GITHUB_GETLIBLIST_H_
......@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2013 KiCad Developers, see CHANGELOG.TXT for contributors.
* 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
......@@ -101,6 +101,7 @@ Vary: Accept-Encoding
#include <class_module.h>
#include <macros.h>
#include <fp_lib_table.h> // ExpandSubstitutions()
#include <github_getliblist.h>
using namespace std;
......@@ -549,6 +550,57 @@ void GITHUB_PLUGIN::remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR )
}
}
// This GITHUB_GETLIBLIST method should not be here, but in github_getliblist.cpp!
// However it is here just because we need to include <avhttp.hpp> to compile it.
// and if we include avhttp in 2 .cpp files, the link fails becuse it detects duplicate
// avhttp functions.
// So until it is fixed, this code is here.
bool GITHUB_GETLIBLIST::remote_get_json( std::string* aFullURLCommand, wxString* aMsgError )
{
boost::asio::io_service io;
avhttp::http_stream h( io );
avhttp::request_opts options;
options.insert( "Accept", "application/json" );
options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME.
h.request_options( options );
try
{
std::ostringstream os;
h.open( *aFullURLCommand ); // only one file, therefore do it synchronously.
os << &h;
// Keep json text file image in RAM.
m_json_image = os.str();
// 4 lines, using SSL, top that.
}
catch( boost::system::system_error& e )
{
// https "GET" has faild, report this to API caller.
static const char errorcmd[] = "https GET command failed"; // Do not translate this message
UTF8 fmt( _( "%s\nCannot get/download json data from: '%s'\nReason: '%s'" ) );
std::string msg = StrPrintf( fmt.c_str(),
errorcmd,
// Report secret list_url to user. The secret
// list_url may go bad at some point in future if github changes
// their server architecture. Then fix repoURL_zipURL() to reflect
// new architecture.
aFullURLCommand->c_str(), e.what() );
if( aMsgError )
{
*aMsgError = msg;
return false;
}
}
return true;
}
#if 0 && defined(STANDALONE)
......
......@@ -469,20 +469,19 @@ void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte )
if( pt_texte->IsMultilineAllowed() )
{
std::vector<wxPoint> positions;
wxArrayString* list = wxStringSplit( shownText, '\n' );
positions.reserve( list->Count() );
wxArrayString strings_list;
wxStringSplit( shownText, strings_list, '\n' );
positions.reserve( strings_list.Count() );
pt_texte->GetPositionsOfLinesOfMultilineText( positions, list->Count() );
pt_texte->GetPositionsOfLinesOfMultilineText( positions, strings_list.Count() );
for( unsigned ii = 0; ii < list->Count(); ii++ )
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
wxString& txt = list->Item( ii );
wxString& txt = strings_list.Item( ii );
m_plotter->Text( positions[ii], UNSPECIFIED_COLOR, txt, orient, size,
pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
thickness, pt_texte->IsItalic(), allow_bold );
}
delete list;
}
else
{
......
......@@ -98,8 +98,8 @@ EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) :
EDIT_POINT& end = aLine.GetEnd();
// Previous and next points, to make constraining lines (adjacent to the dragged line)
EDIT_POINT& prevOrigin = *aPoints.Previous( origin );
EDIT_POINT& nextEnd = *aPoints.Next( end );
EDIT_POINT& prevOrigin = *aPoints.Previous( origin, false );
EDIT_POINT& nextEnd = *aPoints.Next( end, false );
// Constraints for segments adjacent to the dragged one
m_originSideConstraint = new EC_LINE( origin, prevOrigin );
......@@ -147,8 +147,8 @@ void EC_CONVERGING::Apply( EDIT_LINE& aHandle )
m_originSideConstraint->Apply();
m_endSideConstraint->Apply();
EDIT_POINT& prevOrigin = *m_editPoints.Previous( origin );
EDIT_POINT& nextEnd = *m_editPoints.Next( end );
EDIT_POINT& prevOrigin = *m_editPoints.Previous( origin, false );
EDIT_POINT& nextEnd = *m_editPoints.Next( end, false );
// Two segments adjacent to the dragged segment
SEG originSide = SEG( origin.GetPosition(), prevOrigin.GetPosition() );
......
......@@ -60,22 +60,86 @@ EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation )
std::deque<EDIT_LINE>::iterator lit, litEnd;
for( lit = m_lines.begin(), litEnd = m_lines.end(); lit != litEnd; ++lit )
{
EDIT_LINE& point = *lit;
EDIT_LINE& line = *lit;
if( point.WithinPoint( aLocation, size ) )
return &point;
if( line.WithinPoint( aLocation, size ) )
return &line;
}
return NULL;
}
EDIT_POINT* EDIT_POINTS::Previous( const EDIT_POINT& aPoint )
int EDIT_POINTS::GetContourStartIdx( int aPointIdx ) const
{
int lastIdx = 0;
BOOST_FOREACH( int idx, m_contours )
{
if( idx >= aPointIdx )
return lastIdx;
lastIdx = idx + 1;
}
return lastIdx;
}
int EDIT_POINTS::GetContourEndIdx( int aPointIdx ) const
{
BOOST_FOREACH( int idx, m_contours )
{
if( idx >= aPointIdx )
return idx;
}
return m_points.size() - 1;
}
bool EDIT_POINTS::IsContourStart( int aPointIdx ) const
{
BOOST_FOREACH( int idx, m_contours )
{
if( idx + 1 == aPointIdx )
return true;
// the list is sorted, so we cannot expect it any further
if( idx > aPointIdx )
break;
}
return ( aPointIdx == 0 );
}
bool EDIT_POINTS::IsContourEnd( int aPointIdx ) const
{
BOOST_FOREACH( int idx, m_contours )
{
if( idx == aPointIdx )
return true;
// the list is sorted, so we cannot expect it any further
if( idx > aPointIdx )
break;
}
// the end of the list surely is the end of a contour
return ( aPointIdx == (int) m_points.size() - 1 );
}
EDIT_POINT* EDIT_POINTS::Previous( const EDIT_POINT& aPoint, bool aTraverseContours )
{
for( unsigned int i = 0; i < m_points.size(); ++i )
{
if( m_points[i] == aPoint )
{
if( !aTraverseContours && IsContourStart( i ) )
return &m_points[GetContourEndIdx( i )];
if( i == 0 )
return &m_points[m_points.size() - 1];
else
......@@ -104,12 +168,15 @@ EDIT_LINE* EDIT_POINTS::Previous( const EDIT_LINE& aLine )
}
EDIT_POINT* EDIT_POINTS::Next( const EDIT_POINT& aPoint )
EDIT_POINT* EDIT_POINTS::Next( const EDIT_POINT& aPoint, bool aTraverseContours )
{
for( unsigned int i = 0; i < m_points.size(); ++i )
{
if( m_points[i] == aPoint )
{
if( !aTraverseContours && IsContourEnd( i ) )
return &m_points[GetContourStartIdx( i )];
if( i == m_points.size() - 1 )
return &m_points[0];
else
......@@ -152,7 +219,9 @@ void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
aGal->DrawRectangle( point.GetPosition() - size / 2, point.GetPosition() + size / 2 );
BOOST_FOREACH( const EDIT_LINE& line, m_lines )
{
aGal->DrawCircle( line.GetPosition(), size / 2 );
}
aGal->PopDepth();
}
......@@ -243,7 +243,6 @@ public:
return m_constraint.get();
}
/**
* Function GetOrigin()
*
......@@ -371,16 +370,65 @@ public:
m_lines.push_back( EDIT_LINE( aOrigin, aEnd ) );
}
/**
* Function AddBreak()
*
* Adds a break, indicating the end of a contour.
*/
void AddBreak()
{
assert( m_points.size() > 0 );
m_contours.push_back( m_points.size() - 1 );
}
/**
* Function GetContourStartIdx()
*
* Returns index of the contour origin for a point with given index.
* @param aPointIdx is the index of point for which the contour origin is searched.
* @return Index of the contour origin point.
*/
int GetContourStartIdx( int aPointIdx ) const;
/**
* Function GetContourEndIdx()
*
* Returns index of the contour finish for a point with given index.
* @param aPointIdx is the index of point for which the contour finish is searched.
* @return Index of the contour finish point.
*/
int GetContourEndIdx( int aPointIdx ) const;
/**
* Function IsContourStart()
*
* Checks is a point with given index is a contour origin.
* @param aPointIdx is the index of the point to be checked.
* @return True if the point is an origin of a contour.
*/
bool IsContourStart( int aPointIdx ) const;
/**
* Function IsContourEnd()
*
* Checks is a point with given index is a contour finish.
* @param aPointIdx is the index of the point to be checked.
* @return True if the point is a finish of a contour.
*/
bool IsContourEnd( int aPointIdx ) const;
/**
* Function Previous()
*
* Returns the point that is after the given point in the list.
* @param aPoint is the point that is supposed to be preceding the searched point.
* @param aTraverseContours decides if in case of breaks should we return to the origin
* of contour or continue with the next contour.
* @return The point following aPoint in the list. If aPoint is the first in
* the list, the last from the list will be returned. If there are no points at all, NULL
* is returned.
*/
EDIT_POINT* Previous( const EDIT_POINT& aPoint );
EDIT_POINT* Previous( const EDIT_POINT& aPoint, bool aTraverseContours = true );
EDIT_LINE* Previous( const EDIT_LINE& aLine );
......@@ -389,11 +437,13 @@ public:
*
* Returns the point that is before the given point in the list.
* @param aPoint is the point that is supposed to be following the searched point.
* @param aTraverseContours decides if in case of breaks should we return to the origin
* of contour or continue with the next contour.
* @return The point preceding aPoint in the list. If aPoint is the last in
* the list, the first point from the list will be returned. If there are no points at all,
* NULL is returned.
*/
EDIT_POINT* Next( const EDIT_POINT& aPoint );
EDIT_POINT* Next( const EDIT_POINT& aPoint, bool aTraverseContours = true );
EDIT_LINE* Next( const EDIT_LINE& aLine );
......@@ -461,6 +511,7 @@ private:
EDA_ITEM* m_parent; ///< Parent of the EDIT_POINTs
std::deque<EDIT_POINT> m_points; ///< EDIT_POINTs for modifying m_parent
std::deque<EDIT_LINE> m_lines; ///< EDIT_LINEs for modifying m_parent
std::list<int> m_contours; ///< Indices of end contour points
};
#endif /* EDIT_POINTS_H_ */
......@@ -119,20 +119,35 @@ public:
int cornersCount = outline->GetCornersCount();
for( int i = 0; i < cornersCount; ++i )
{
points->AddPoint( outline->GetPos( i ) );
if( outline->IsEndContour( i ) )
points->AddBreak();
}
// Lines have to be added after creating edit points,
// as they use EDIT_POINT references
for( int i = 0; i < cornersCount - 1; ++i )
{
points->AddLine( points->Point( i ), points->Point( i + 1 ) );
points->Line( i ).SetConstraint(
new EC_SNAPLINE( points->Line( i ),
if( points->IsContourEnd( i ) )
{
points->AddLine( points->Point( i ),
points->Point( points->GetContourStartIdx( i ) ) );
}
else
{
points->AddLine( points->Point( i ), points->Point( i + 1 ) );
}
points->Line( i ).SetConstraint( new EC_SNAPLINE( points->Line( i ),
boost::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
}
// The last missing line, connecting the last and the first polygon point
points->AddLine( points->Point( cornersCount - 1 ), points->Point( 0 ) );
points->AddLine( points->Point( cornersCount - 1 ),
points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) );
points->Line( points->LinesSize() - 1 ).SetConstraint(
new EC_SNAPLINE( points->Line( points->LinesSize() - 1 ),
boost::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
......
update=30/03/2013 13:45:59
update=11/01/2015 18:31:38
version=1
last_client=pcbnew
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[cvpcb]
version=1
NetIExt=net
[cvpcb/libraries]
EquName1=devcms
[eeschema]
version=1
LibDir=
......@@ -68,3 +63,6 @@ SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
[cvpcb]
version=1
NetIExt=net
......@@ -200,6 +200,9 @@ void BOARD_OUTLINE::readOutlines( std::ifstream& aBoardFile, IDF3::IDF_VERSION a
// rewind to the start of the last line; the routine invoking
// this is responsible for checking that the current '.END_ ...'
// matches the section header.
if(aBoardFile.eof())
aBoardFile.clear();
aBoardFile.seekg( pos );
if( outlines.size() > 0 )
......@@ -2998,6 +3001,9 @@ void IDF3_COMP_OUTLINE::readProperties( std::ifstream& aLibFile )
if( token.size() >= 5 && CompareToken( ".END_", token.substr( 0, 5 ) ) )
{
if(aLibFile.eof())
aLibFile.clear();
aLibFile.seekg( pos );
return;
}
......
......@@ -2306,7 +2306,7 @@ void IDF3_BOARD::readBoardFile( const std::string& aFileName, bool aNoSubstitute
try
{
brd.open( aFileName.c_str(), std::ios_base::in );
brd.open( aFileName.c_str(), std::ios_base::in | std::ios_base::binary );
if( !brd.is_open() )
{
......@@ -2682,7 +2682,7 @@ void IDF3_BOARD::readLibFile( const std::string& aFileName )
try
{
lib.open( aFileName.c_str(), std::ios_base::in );
lib.open( aFileName.c_str(), std::ios_base::in | std::ios_base::binary );
IDF3::FILE_STATE state = IDF3::FILE_START;
......@@ -3883,7 +3883,7 @@ IDF3_COMP_OUTLINE* IDF3_BOARD::GetComponentOutline( wxString aFullFileName )
try
{
model.open( fname.c_str(), std::ios_base::in );
model.open( fname.c_str(), std::ios_base::in | std::ios_base::binary );
std::string iline; // the input line
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment