kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #30564
Re: [PATCH] Math expression support for pad editor.
Creating a variable looks a bit complicated to me. And if I see it
correctly it is not possible with exprtk to use constants with units
(0.16").
Maybe it would be possible to provide functions that do the math like
fromInch(0.16).
That is the beauty of a parser generator. You can define the desired syntax
yourself.
I have added support for variables to my parser approach. Now I can write
things like this:
[Scratch Pad, global unit set to inch]
e=0.4mm; L=0.8mm; E=2.5mm
PosX: -3.5*e
PosY: E/2-L/2+0.1mm
I have attached a patch of my implementation. It adds the evaluator (object
size ~120kB) and includes it to the pad- and footprint dialogs.
The pad dialog contains a (misaligned and too small) scratch pad.
The code is a mess and wouldn't make it into Kicad. But it works for me and
maybe you'll end up with your own parser solution.
The interface is not too different from exprtk so you wouldn't have to
throw away your work. If you want to play with the grammar
file you'll need the lemon parser generator ($ lemon grammar.lemon).
- Michael
On Fri, Sep 1, 2017 at 3:23 AM, Russell Oliver <roliver8143@xxxxxxxxx>
wrote:
> Scratch Pad:
> I think this will be easily doable as an additional text box in the
> dialog, which is then added to the beginning of the expression for each
> text box. The format for the math library is as follows
>
> (a) Initialise x to zero
> var x;
>
> (b) Initialise y to three
> var y := 3;
>
> (c) Initialise z to the expression
> var z := if (max(1,x + y) > 2,w,v);
>
> Global variable support:
> I think this is possible but a simpler path might be to use a global
> scratch pad, which would be added first to the beginning of the expression
> used for the text box.
>
> Currently the expression text ie something like "posx + 1" isn't saved
> within the dialog or for the component.
>
> Regards
> Russell
>
>
>
>
>
> On Fri, Sep 1, 2017 at 7:46 AM Michael Geselbracht <
> mgeselbracht3@xxxxxxxxx> wrote:
>
>> Hi,
>>
>> I have tested the patch and I really like this feature. This automatic
>> variable assignment will sure come in handy.
>> How about adding a kind of scratch pad (a single line should do) to the
>> footprint editor so that one can add variables (measurements) given in
>> datasheets?
>> Like "c1=2.9; e=0.635" in the scratch pad and then in PosX field: "-c1/2
>> " and PosY: "-1.5*e" in order to place the first pad.
>>
>> - Michael
>>
>>
>> On Thu, Aug 31, 2017 at 3:58 PM, Tomasz Wlostowski <
>> tomasz.wlostowski@xxxxxxx> wrote:
>>
>>> On 31.08.2017 15:27, Russell Oliver wrote:
>>> > Hi All.
>>> >
>>> > As a follow up to my earlier post, attached is a patch that implement
>>> > math expressions in the pad editor as well.
>>> >
>>> > A nifty feature is that the fields can be referenced from each other.
>>> > currently the fields are referenced by the following names.
>>> > - posx, posy, sizex, sizey, offsetx, offsetx, drillx, drillx.
>>>
>>> Hi Russell,
>>>
>>> Didn't have the time to check your patch yet, but I came up with an
>>> idea: add global variable support to the math parser, so that if you
>>> place a text anywhere in the design assigning to a variable (e.g.
>>> var=10), it will be updated in any of the expressions that reference it.
>>>
>>> Cheers,
>>> Tom
>>>
>>> _______________________________________________
>>> Mailing list: https://launchpad.net/~kicad-developers
>>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
>>> Unsubscribe : https://launchpad.net/~kicad-developers
>>> More help : https://help.launchpad.net/ListHelp
>>>
>>
>> _______________________________________________
>> Mailing list: https://launchpad.net/~kicad-developers
>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
>> Unsubscribe : https://launchpad.net/~kicad-developers
>> More help : https://help.launchpad.net/ListHelp
>>
>
From efb30f8057d5d9e609eb629a2fb14feeb5762c11 Mon Sep 17 00:00:00 2001
From: Michael Geselbracht <mgeselbracht@xxxxxxxxxx>
Date: Mon, 28 Aug 2017 00:11:49 +0200
Subject: [PATCH] Add: Calculating text entry fields
Add units
Fix: Endless loop when using inch (")
Pad Properties: Make 1st page default again
Variable support
---
.gitignore | 9 +-
common/CMakeLists.txt | 3 +
common/base_units.cpp | 7 +
common/libeval/grammar.c | 1086 ++++++++++++++++++++
common/libeval/grammar.h | 12 +
common/libeval/grammar.lemon | 47 +
common/libeval/numeric_evaluator.cpp | 302 ++++++
common/libeval/numeric_evaluator.h | 86 ++
pcbnew/CMakeLists.txt | 2 +
.../dialogs/dialog_edit_module_for_BoardEditor.cpp | 25 +
.../dialogs/dialog_edit_module_for_BoardEditor.h | 7 +
.../dialog_edit_module_for_BoardEditor_base.cpp | 22 +-
.../dialog_edit_module_for_BoardEditor_base.fbp | 20 +-
.../dialog_edit_module_for_BoardEditor_base.h | 4 +-
pcbnew/dialogs/dialog_move_exact.cpp | 5 +
pcbnew/dialogs/dialog_move_exact.h | 4 +
pcbnew/dialogs/dialog_pad_properties.cpp | 26 +
pcbnew/dialogs/dialog_pad_properties.h | 7 +-
pcbnew/dialogs/dialog_pad_properties_base.cpp | 90 +-
pcbnew/dialogs/dialog_pad_properties_base.fbp | 326 ++++--
pcbnew/dialogs/dialog_pad_properties_base.h | 8 +-
pcbnew/dialogs/dialog_position_relative.cpp | 14 +
pcbnew/dialogs/dialog_position_relative.h | 6 +
23 files changed, 2032 insertions(+), 86 deletions(-)
create mode 100644 common/libeval/grammar.c
create mode 100644 common/libeval/grammar.h
create mode 100644 common/libeval/grammar.lemon
create mode 100644 common/libeval/numeric_evaluator.cpp
create mode 100644 common/libeval/numeric_evaluator.h
diff --git a/.gitignore b/.gitignore
index d80bf3899..7e5cbdbac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,4 +73,11 @@ demos/**/_autosave-*
*.old
*.gch
*.orig
-*.patch
\ No newline at end of file
+*.patch
+
+# let
+/let/
+/.project
+/.cproject
+/.settings/
+
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 42fa4ddb2..ee53cbcea 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -8,6 +8,7 @@ include_directories(
./dialogs
./widgets
./dialog_about
+ ./libeval
${CAIRO_INCLUDE_DIR}
${PIXMAN_INCLUDE_DIR}
${GLEW_INCLUDE_DIR}
@@ -346,6 +347,8 @@ set( COMMON_SRCS
geometry/shape_collisions.cpp
geometry/shape_file_io.cpp
geometry/convex_hull.cpp
+
+ libeval/numeric_evaluator.cpp
)
add_library( common STATIC ${COMMON_SRCS} )
add_dependencies( common lib-dependencies )
diff --git a/common/base_units.cpp b/common/base_units.cpp
index 4611b182d..1087f08f4 100644
--- a/common/base_units.cpp
+++ b/common/base_units.cpp
@@ -39,6 +39,7 @@
#include <class_title_block.h>
#include <common.h>
#include <base_units.h>
+#include "libeval/numeric_evaluator.h"
#if defined( PCBNEW ) || defined( CVPCB ) || defined( EESCHEMA ) || defined( GERBVIEW ) || defined( PL_EDITOR )
@@ -386,6 +387,12 @@ int ValueFromTextCtrl( const wxTextCtrl& aTextCtr )
int value;
wxString msg = aTextCtr.GetValue();
+ NumericEvaluator eval;
+ if (eval.process(msg.mb_str()))
+ {
+ msg = wxString::FromUTF8(eval.result());
+ }
+
value = ValueFromString( g_UserUnit, msg );
return value;
diff --git a/common/libeval/grammar.c b/common/libeval/grammar.c
new file mode 100644
index 000000000..705f20b97
--- /dev/null
+++ b/common/libeval/grammar.c
@@ -0,0 +1,1086 @@
+/*
+** 2000-05-29
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Driver template for the LEMON parser generator.
+**
+** The "lemon" program processes an LALR(1) input grammar file, then uses
+** this template to construct a parser. The "lemon" program inserts text
+** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
+** interstitial "-" characters) contained in this template is changed into
+** the value of the %name directive from the grammar. Otherwise, the content
+** of this template is copied straight through into the generate parser
+** source file.
+**
+** The following is the concatenation of all %include directives from the
+** input grammar file:
+*/
+#include <stdio.h>
+/************ Begin %include sections from the grammar ************************/
+#line 8 "grammar.lemon"
+
+#include <assert.h>
+#include <math.h>
+#include "numeric_evaluator.h"
+#line 33 "grammar.c"
+/**************** End of %include directives **********************************/
+/* These constants specify the various numeric values for terminal symbols
+** in a format understandable to "makeheaders". This section is blank unless
+** "lemon" is run with the "-m" command-line option.
+***************** Begin makeheaders token definitions *************************/
+/**************** End makeheaders token definitions ***************************/
+
+/* The next sections is a series of control #defines.
+** various aspects of the generated parser.
+** YYCODETYPE is the data type used to store the integer codes
+** that represent terminal and non-terminal symbols.
+** "unsigned char" is used if there are fewer than
+** 256 symbols. Larger types otherwise.
+** YYNOCODE is a number of type YYCODETYPE that is not used for
+** any terminal or nonterminal symbol.
+** YYFALLBACK If defined, this indicates that one or more tokens
+** (also known as: "terminal symbols") have fall-back
+** values which should be used if the original symbol
+** would not parse. This permits keywords to sometimes
+** be used as identifiers, for example.
+** YYACTIONTYPE is the data type used for "action codes" - numbers
+** that indicate what to do in response to the next
+** token.
+** ParseTOKENTYPE is the data type used for minor type for terminal
+** symbols. Background: A "minor type" is a semantic
+** value associated with a terminal or non-terminal
+** symbols. For example, for an "ID" terminal symbol,
+** the minor type might be the name of the identifier.
+** Each non-terminal can have a different minor type.
+** Terminal symbols all have the same minor type, though.
+** This macros defines the minor type for terminal
+** symbols.
+** YYMINORTYPE is the data type used for all minor types.
+** This is typically a union of many types, one of
+** which is ParseTOKENTYPE. The entry in the union
+** for terminal symbols is called "yy0".
+** YYSTACKDEPTH is the maximum depth of the parser's stack. If
+** zero the stack is dynamically sized using realloc()
+** ParseARG_SDECL A static variable declaration for the %extra_argument
+** ParseARG_PDECL A parameter declaration for the %extra_argument
+** ParseARG_STORE Code to store %extra_argument into yypParser
+** ParseARG_FETCH Code to extract %extra_argument from yypParser
+** YYERRORSYMBOL is the code number of the error symbol. If not
+** defined, then do no error processing.
+** YYNSTATE the combined number of states.
+** YYNRULE the number of rules in the grammar
+** YY_MAX_SHIFT Maximum value for shift actions
+** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
+** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
+** YY_MIN_REDUCE Maximum value for reduce actions
+** YY_ERROR_ACTION The yy_action[] code for syntax error
+** YY_ACCEPT_ACTION The yy_action[] code for accept
+** YY_NO_ACTION The yy_action[] code for no-op
+*/
+#ifndef INTERFACE
+# define INTERFACE 1
+#endif
+/************* Begin control #defines *****************************************/
+#define YYCODETYPE unsigned char
+#define YYNOCODE 19
+#define YYACTIONTYPE unsigned char
+#define ParseTOKENTYPE numEval::TokenType
+typedef union {
+ int yyinit;
+ ParseTOKENTYPE yy0;
+} YYMINORTYPE;
+#ifndef YYSTACKDEPTH
+#define YYSTACKDEPTH 100
+#endif
+#define ParseARG_SDECL NumericEvaluator* pEval ;
+#define ParseARG_PDECL , NumericEvaluator* pEval
+#define ParseARG_FETCH NumericEvaluator* pEval = yypParser->pEval
+#define ParseARG_STORE yypParser->pEval = pEval
+#define YYNSTATE 17
+#define YYNRULE 16
+#define YY_MAX_SHIFT 16
+#define YY_MIN_SHIFTREDUCE 26
+#define YY_MAX_SHIFTREDUCE 41
+#define YY_MIN_REDUCE 42
+#define YY_MAX_REDUCE 57
+#define YY_ERROR_ACTION 58
+#define YY_ACCEPT_ACTION 59
+#define YY_NO_ACTION 60
+/************* End control #defines *******************************************/
+
+/* The yyzerominor constant is used to initialize instances of
+** YYMINORTYPE objects to zero. */
+static const YYMINORTYPE yyzerominor = { 0 };
+
+/* Define the yytestcase() macro to be a no-op if is not already defined
+** otherwise.
+**
+** Applications can choose to define yytestcase() in the %include section
+** to a macro that can assist in verifying code coverage. For production
+** code the yytestcase() macro should be turned off. But it is useful
+** for testing.
+*/
+#ifndef yytestcase
+# define yytestcase(X)
+#endif
+
+
+/* Next are the tables used to determine what action to take based on the
+** current state and lookahead token. These tables are used to implement
+** functions that take a state number and lookahead value and return an
+** action integer.
+**
+** Suppose the action integer is N. Then the action is determined as
+** follows
+**
+** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
+** token onto the stack and goto state N.
+**
+** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
+** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
+**
+** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
+** and YY_MAX_REDUCE
+
+** N == YY_ERROR_ACTION A syntax error has occurred.
+**
+** N == YY_ACCEPT_ACTION The parser accepts its input.
+**
+** N == YY_NO_ACTION No such action. Denotes unused
+** slots in the yy_action[] table.
+**
+** The action table is constructed as a single large table named yy_action[].
+** Given state S and lookahead X, the action is computed as
+**
+** yy_action[ yy_shift_ofst[S] + X ]
+**
+** If the index value yy_shift_ofst[S]+X is out of range or if the value
+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+** and that yy_default[S] should be used instead.
+**
+** The formula above is for computing the action when the lookahead is
+** a terminal symbol. If the lookahead is a non-terminal (as occurs after
+** a reduce action) then the yy_reduce_ofst[] array is used in place of
+** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
+** YY_SHIFT_USE_DFLT.
+**
+** The following are the tables generated in this section:
+**
+** yy_action[] A single table containing all actions.
+** yy_lookahead[] A table containing the lookahead for each entry in
+** yy_action. Used to detect hash collisions.
+** yy_shift_ofst[] For each state, the offset into yy_action for
+** shifting terminals.
+** yy_reduce_ofst[] For each state, the offset into yy_action for
+** shifting non-terminals after a reduce.
+** yy_default[] Default action for each state.
+**
+*********** Begin parsing tables **********************************************/
+#define YY_ACTTAB_COUNT (48)
+static const YYACTIONTYPE yy_action[] = {
+ /* 0 */ 42, 15, 59, 1, 27, 9, 7, 28, 9, 29,
+ /* 10 */ 16, 2, 3, 4, 31, 8, 6, 3, 4, 30,
+ /* 20 */ 15, 8, 6, 3, 4, 7, 10, 44, 29, 16,
+ /* 30 */ 2, 8, 6, 3, 4, 15, 33, 40, 41, 39,
+ /* 40 */ 7, 11, 13, 5, 16, 2, 14, 12,
+};
+static const YYCODETYPE yy_lookahead[] = {
+ /* 0 */ 0, 1, 14, 15, 16, 17, 6, 16, 17, 9,
+ /* 10 */ 10, 11, 7, 8, 4, 5, 6, 7, 8, 9,
+ /* 20 */ 1, 5, 6, 7, 8, 6, 17, 18, 9, 10,
+ /* 30 */ 11, 5, 6, 7, 8, 1, 3, 17, 12, 17,
+ /* 40 */ 6, 17, 17, 2, 10, 11, 17, 17,
+};
+#define YY_SHIFT_USE_DFLT (-1)
+#define YY_SHIFT_COUNT (16)
+#define YY_SHIFT_MIN (0)
+#define YY_SHIFT_MAX (41)
+static const signed char yy_shift_ofst[] = {
+ /* 0 */ 19, 0, 34, 34, 34, 34, 34, 34, 34, 10,
+ /* 10 */ 26, 16, 5, 5, 5, 41, 33,
+};
+#define YY_REDUCE_USE_DFLT (-13)
+#define YY_REDUCE_COUNT (8)
+#define YY_REDUCE_MIN (-12)
+#define YY_REDUCE_MAX (30)
+static const signed char yy_reduce_ofst[] = {
+ /* 0 */ -12, -9, 9, 20, 22, 24, 25, 29, 30,
+};
+static const YYACTIONTYPE yy_default[] = {
+ /* 0 */ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ /* 10 */ 58, 52, 53, 54, 50, 51, 48,
+};
+/********** End of lemon-generated parsing tables *****************************/
+
+/* The next table maps tokens (terminal symbols) into fallback tokens.
+** If a construct like the following:
+**
+** %fallback ID X Y Z.
+**
+** appears in the grammar, then ID becomes a fallback token for X, Y,
+** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
+** but it does not parse, the type of the token is changed to ID and
+** the parse is retried before an error is thrown.
+**
+** This feature can be used, for example, to cause some keywords in a language
+** to revert to identifiers if they keyword does not apply in the context where
+** it appears.
+*/
+#ifdef YYFALLBACK
+static const YYCODETYPE yyFallback[] = {
+};
+#endif /* YYFALLBACK */
+
+/* The following structure represents a single element of the
+** parser's stack. Information stored includes:
+**
+** + The state number for the parser at this level of the stack.
+**
+** + The value of the token stored at this level of the stack.
+** (In other words, the "major" token.)
+**
+** + The semantic value stored at this level of the stack. This is
+** the information used by the action routines in the grammar.
+** It is sometimes called the "minor" token.
+**
+** After the "shift" half of a SHIFTREDUCE action, the stateno field
+** actually contains the reduce action for the second half of the
+** SHIFTREDUCE.
+*/
+struct yyStackEntry {
+ YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
+ YYCODETYPE major; /* The major token value. This is the code
+ ** number for the token at this stack level */
+ YYMINORTYPE minor; /* The user-supplied minor token value. This
+ ** is the value of the token */
+};
+typedef struct yyStackEntry yyStackEntry;
+
+/* The state of the parser is completely contained in an instance of
+** the following structure */
+struct yyParser {
+ int yyidx; /* Index of top element in stack */
+#ifdef YYTRACKMAXSTACKDEPTH
+ int yyidxMax; /* Maximum value of yyidx */
+#endif
+ int yyerrcnt; /* Shifts left before out of the error */
+ ParseARG_SDECL /* A place to hold %extra_argument */
+#if YYSTACKDEPTH<=0
+ int yystksz; /* Current side of the stack */
+ yyStackEntry *yystack; /* The parser's stack */
+#else
+ yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
+#endif
+};
+typedef struct yyParser yyParser;
+
+#ifndef NDEBUG
+#include <stdio.h>
+static FILE *yyTraceFILE = 0;
+static char *yyTracePrompt = 0;
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/*
+** Turn parser tracing on by giving a stream to which to write the trace
+** and a prompt to preface each trace message. Tracing is turned off
+** by making either argument NULL
+**
+** Inputs:
+** <ul>
+** <li> A FILE* to which trace output should be written.
+** If NULL, then tracing is turned off.
+** <li> A prefix string written at the beginning of every
+** line of trace output. If NULL, then tracing is
+** turned off.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
+ yyTraceFILE = TraceFILE;
+ yyTracePrompt = zTracePrompt;
+ if( yyTraceFILE==0 ) yyTracePrompt = 0;
+ else if( yyTracePrompt==0 ) yyTraceFILE = 0;
+}
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing shifts, the names of all terminals and nonterminals
+** are required. The following table supplies these names */
+static const char *const yyTokenName[] = {
+ "$", "VAR", "ASSIGN", "UNIT",
+ "SEMCOL", "PLUS", "MINUS", "DIVIDE",
+ "MULT", "ENDS", "VALUE", "PARENL",
+ "PARENR", "error", "main", "in",
+ "stmt", "expr",
+};
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing reduce actions, the names of all rules are required.
+*/
+static const char *const yyRuleName[] = {
+ /* 0 */ "main ::= in",
+ /* 1 */ "in ::= stmt",
+ /* 2 */ "in ::= in stmt",
+ /* 3 */ "stmt ::= ENDS",
+ /* 4 */ "stmt ::= expr ENDS",
+ /* 5 */ "stmt ::= expr SEMCOL",
+ /* 6 */ "expr ::= VALUE",
+ /* 7 */ "expr ::= VALUE UNIT",
+ /* 8 */ "expr ::= MINUS expr",
+ /* 9 */ "expr ::= VAR",
+ /* 10 */ "expr ::= VAR ASSIGN expr",
+ /* 11 */ "expr ::= expr PLUS expr",
+ /* 12 */ "expr ::= expr MINUS expr",
+ /* 13 */ "expr ::= expr MULT expr",
+ /* 14 */ "expr ::= expr DIVIDE expr",
+ /* 15 */ "expr ::= PARENL expr PARENR",
+};
+#endif /* NDEBUG */
+
+
+#if YYSTACKDEPTH<=0
+/*
+** Try to increase the size of the parser stack.
+*/
+static void yyGrowStack(yyParser *p){
+ int newSize;
+ yyStackEntry *pNew;
+
+ newSize = p->yystksz*2 + 100;
+ pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
+ if( pNew ){
+ p->yystack = pNew;
+ p->yystksz = newSize;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
+ yyTracePrompt, p->yystksz);
+ }
+#endif
+ }
+}
+#endif
+
+/* Datatype of the argument to the memory allocated passed as the
+** second argument to ParseAlloc() below. This can be changed by
+** putting an appropriate #define in the %include section of the input
+** grammar.
+*/
+#ifndef YYMALLOCARGTYPE
+# define YYMALLOCARGTYPE size_t
+#endif
+
+/*
+** This function allocates a new parser.
+** The only argument is a pointer to a function which works like
+** malloc.
+**
+** Inputs:
+** A pointer to the function used to allocate memory.
+**
+** Outputs:
+** A pointer to a parser. This pointer is used in subsequent calls
+** to Parse and ParseFree.
+*/
+void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
+ yyParser *pParser;
+ pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
+ if( pParser ){
+ pParser->yyidx = -1;
+#ifdef YYTRACKMAXSTACKDEPTH
+ pParser->yyidxMax = 0;
+#endif
+#if YYSTACKDEPTH<=0
+ pParser->yystack = NULL;
+ pParser->yystksz = 0;
+ yyGrowStack(pParser);
+#endif
+ }
+ return pParser;
+}
+
+/* The following function deletes the "minor type" or semantic value
+** associated with a symbol. The symbol can be either a terminal
+** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
+** a pointer to the value to be deleted. The code used to do the
+** deletions is derived from the %destructor and/or %token_destructor
+** directives of the input grammar.
+*/
+static void yy_destructor(
+ yyParser *yypParser, /* The parser */
+ YYCODETYPE yymajor, /* Type code for object to destroy */
+ YYMINORTYPE *yypminor /* The object to be destroyed */
+){
+ ParseARG_FETCH;
+ switch( yymajor ){
+ /* Here is inserted the actions which take place when a
+ ** terminal or non-terminal is destroyed. This can happen
+ ** when the symbol is popped from the stack during a
+ ** reduce or during error processing or when a parser is
+ ** being destroyed before it is finished parsing.
+ **
+ ** Note: during a reduce, the only symbols destroyed are those
+ ** which appear on the RHS of the rule, but which are *not* used
+ ** inside the C code.
+ */
+/********* Begin destructor definitions ***************************************/
+/********* End destructor definitions *****************************************/
+ default: break; /* If no destructor action specified: do nothing */
+ }
+}
+
+/*
+** Pop the parser's stack once.
+**
+** If there is a destructor routine associated with the token which
+** is popped from the stack, then call it.
+*/
+static void yy_pop_parser_stack(yyParser *pParser){
+ yyStackEntry *yytos;
+ assert( pParser->yyidx>=0 );
+ yytos = &pParser->yystack[pParser->yyidx--];
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sPopping %s\n",
+ yyTracePrompt,
+ yyTokenName[yytos->major]);
+ }
+#endif
+ yy_destructor(pParser, yytos->major, &yytos->minor);
+}
+
+/*
+** Deallocate and destroy a parser. Destructors are called for
+** all stack elements before shutting the parser down.
+**
+** If the YYPARSEFREENEVERNULL macro exists (for example because it
+** is defined in a %include section of the input grammar) then it is
+** assumed that the input pointer is never NULL.
+*/
+void ParseFree(
+ void *p, /* The parser to be deleted */
+ void (*freeProc)(void*) /* Function used to reclaim memory */
+){
+ yyParser *pParser = (yyParser*)p;
+#ifndef YYPARSEFREENEVERNULL
+ if( pParser==0 ) return;
+#endif
+ while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
+#if YYSTACKDEPTH<=0
+ free(pParser->yystack);
+#endif
+ (*freeProc)((void*)pParser);
+}
+
+/*
+** Return the peak depth of the stack for a parser.
+*/
+#ifdef YYTRACKMAXSTACKDEPTH
+int ParseStackPeak(void *p){
+ yyParser *pParser = (yyParser*)p;
+ return pParser->yyidxMax;
+}
+#endif
+
+/*
+** Find the appropriate action for a parser given the terminal
+** look-ahead token iLookAhead.
+*/
+static int yy_find_shift_action(
+ yyParser *pParser, /* The parser */
+ YYCODETYPE iLookAhead /* The look-ahead token */
+){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+
+ if( stateno>=YY_MIN_REDUCE ) return stateno;
+ assert( stateno <= YY_SHIFT_COUNT );
+ do{
+ i = yy_shift_ofst[stateno];
+ if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
+ assert( iLookAhead!=YYNOCODE );
+ i += iLookAhead;
+ if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
+ if( iLookAhead>0 ){
+#ifdef YYFALLBACK
+ YYCODETYPE iFallback; /* Fallback token */
+ if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
+ && (iFallback = yyFallback[iLookAhead])!=0 ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+ }
+#endif
+ assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
+ iLookAhead = iFallback;
+ continue;
+ }
+#endif
+#ifdef YYWILDCARD
+ {
+ int j = i - iLookAhead + YYWILDCARD;
+ if(
+#if YY_SHIFT_MIN+YYWILDCARD<0
+ j>=0 &&
+#endif
+#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
+ j<YY_ACTTAB_COUNT &&
+#endif
+ yy_lookahead[j]==YYWILDCARD
+ ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead],
+ yyTokenName[YYWILDCARD]);
+ }
+#endif /* NDEBUG */
+ return yy_action[j];
+ }
+ }
+#endif /* YYWILDCARD */
+ }
+ return yy_default[stateno];
+ }else{
+ return yy_action[i];
+ }
+ }while(1);
+}
+
+/*
+** Find the appropriate action for a parser given the non-terminal
+** look-ahead token iLookAhead.
+*/
+static int yy_find_reduce_action(
+ int stateno, /* Current state number */
+ YYCODETYPE iLookAhead /* The look-ahead token */
+){
+ int i;
+#ifdef YYERRORSYMBOL
+ if( stateno>YY_REDUCE_COUNT ){
+ return yy_default[stateno];
+ }
+#else
+ assert( stateno<=YY_REDUCE_COUNT );
+#endif
+ i = yy_reduce_ofst[stateno];
+ assert( i!=YY_REDUCE_USE_DFLT );
+ assert( iLookAhead!=YYNOCODE );
+ i += iLookAhead;
+#ifdef YYERRORSYMBOL
+ if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
+ return yy_default[stateno];
+ }
+#else
+ assert( i>=0 && i<YY_ACTTAB_COUNT );
+ assert( yy_lookahead[i]==iLookAhead );
+#endif
+ return yy_action[i];
+}
+
+/*
+** The following routine is called if the stack overflows.
+*/
+static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
+ ParseARG_FETCH;
+ yypParser->yyidx--;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
+ }
+#endif
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will execute if the parser
+ ** stack every overflows */
+/******** Begin %stack_overflow code ******************************************/
+/******** End %stack_overflow code ********************************************/
+ ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
+}
+
+/*
+** Print tracing information for a SHIFT action
+*/
+#ifndef NDEBUG
+static void yyTraceShift(yyParser *yypParser, int yyNewState){
+ if( yyTraceFILE ){
+ if( yyNewState<YYNSTATE ){
+ fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n",
+ yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major],
+ yyNewState);
+ }else{
+ fprintf(yyTraceFILE,"%sShift '%s'\n",
+ yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]);
+ }
+ }
+}
+#else
+# define yyTraceShift(X,Y)
+#endif
+
+/*
+** Perform a shift action.
+*/
+static void yy_shift(
+ yyParser *yypParser, /* The parser to be shifted */
+ int yyNewState, /* The new state to shift in */
+ int yyMajor, /* The major token to shift in */
+ YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
+){
+ yyStackEntry *yytos;
+ yypParser->yyidx++;
+#ifdef YYTRACKMAXSTACKDEPTH
+ if( yypParser->yyidx>yypParser->yyidxMax ){
+ yypParser->yyidxMax = yypParser->yyidx;
+ }
+#endif
+#if YYSTACKDEPTH>0
+ if( yypParser->yyidx>=YYSTACKDEPTH ){
+ yyStackOverflow(yypParser, yypMinor);
+ return;
+ }
+#else
+ if( yypParser->yyidx>=yypParser->yystksz ){
+ yyGrowStack(yypParser);
+ if( yypParser->yyidx>=yypParser->yystksz ){
+ yyStackOverflow(yypParser, yypMinor);
+ return;
+ }
+ }
+#endif
+ yytos = &yypParser->yystack[yypParser->yyidx];
+ yytos->stateno = (YYACTIONTYPE)yyNewState;
+ yytos->major = (YYCODETYPE)yyMajor;
+ yytos->minor = *yypMinor;
+ yyTraceShift(yypParser, yyNewState);
+}
+
+/* The following table contains information about every rule that
+** is used during the reduce.
+*/
+static const struct {
+ YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
+ unsigned char nrhs; /* Number of right-hand side symbols in the rule */
+} yyRuleInfo[] = {
+ { 14, 1 },
+ { 15, 1 },
+ { 15, 2 },
+ { 16, 1 },
+ { 16, 2 },
+ { 16, 2 },
+ { 17, 1 },
+ { 17, 2 },
+ { 17, 2 },
+ { 17, 1 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+};
+
+static void yy_accept(yyParser*); /* Forward Declaration */
+
+/*
+** Perform a reduce action and the shift that must immediately
+** follow the reduce.
+*/
+static void yy_reduce(
+ yyParser *yypParser, /* The parser */
+ int yyruleno /* Number of the rule by which to reduce */
+){
+ int yygoto; /* The next state */
+ int yyact; /* The next action */
+ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
+ yyStackEntry *yymsp; /* The top of the parser's stack */
+ int yysize; /* Amount to pop the stack */
+ ParseARG_FETCH;
+ yymsp = &yypParser->yystack[yypParser->yyidx];
+#ifndef NDEBUG
+ if( yyTraceFILE && yyruleno>=0
+ && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+ yysize = yyRuleInfo[yyruleno].nrhs;
+ fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
+ yyRuleName[yyruleno], yymsp[-yysize].stateno);
+ }
+#endif /* NDEBUG */
+ yygotominor = yyzerominor;
+
+ switch( yyruleno ){
+ /* Beginning here are the reduction cases. A typical example
+ ** follows:
+ ** case 0:
+ ** #line <lineno> <grammarfile>
+ ** { ... } // User supplied code
+ ** #line <lineno> <thisfile>
+ ** break;
+ */
+/********** Begin reduce actions **********************************************/
+ case 4: /* stmt ::= expr ENDS */
+#line 28 "grammar.lemon"
+{ pEval->parseSetResult(yymsp[-1].minor.yy0.valid ? yymsp[-1].minor.yy0.dValue : NAN); }
+#line 736 "grammar.c"
+ break;
+ case 5: /* stmt ::= expr SEMCOL */
+#line 29 "grammar.lemon"
+{ pEval->parseSetResult(NAN); }
+#line 741 "grammar.c"
+ break;
+ case 6: /* expr ::= VALUE */
+#line 31 "grammar.lemon"
+{ yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=true; }
+#line 746 "grammar.c"
+ break;
+ case 7: /* expr ::= VALUE UNIT */
+#line 32 "grammar.lemon"
+{ yygotominor.yy0.dValue = yymsp[-1].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=true; }
+#line 751 "grammar.c"
+ break;
+ case 8: /* expr ::= MINUS expr */
+#line 33 "grammar.lemon"
+{ yygotominor.yy0.dValue = -yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; }
+#line 756 "grammar.c"
+ break;
+ case 9: /* expr ::= VAR */
+#line 34 "grammar.lemon"
+{ yygotominor.yy0.dValue = pEval->getVar(yymsp[0].minor.yy0.text); yygotominor.yy0.valid=true; }
+#line 761 "grammar.c"
+ break;
+ case 10: /* expr ::= VAR ASSIGN expr */
+#line 35 "grammar.lemon"
+{ pEval->setVar(yymsp[-2].minor.yy0.text, yymsp[0].minor.yy0.dValue); yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=false; }
+#line 766 "grammar.c"
+ break;
+ case 11: /* expr ::= expr PLUS expr */
+#line 36 "grammar.lemon"
+{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue + yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; }
+#line 771 "grammar.c"
+ break;
+ case 12: /* expr ::= expr MINUS expr */
+#line 37 "grammar.lemon"
+{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue - yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; }
+#line 776 "grammar.c"
+ break;
+ case 13: /* expr ::= expr MULT expr */
+#line 38 "grammar.lemon"
+{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; }
+#line 781 "grammar.c"
+ break;
+ case 14: /* expr ::= expr DIVIDE expr */
+#line 39 "grammar.lemon"
+{
+ if (yymsp[0].minor.yy0.dValue != 0.0) {
+ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue / yymsp[0].minor.yy0.dValue;
+ }
+ else pEval->parseError("Div by zero");
+ yygotominor.yy0.valid=yymsp[0].minor.yy0.valid;
+}
+#line 792 "grammar.c"
+ break;
+ case 15: /* expr ::= PARENL expr PARENR */
+#line 46 "grammar.lemon"
+{ yygotominor.yy0.dValue = yymsp[-1].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[-1].minor.yy0.valid; }
+#line 797 "grammar.c"
+ break;
+ default:
+ /* (0) main ::= in */ yytestcase(yyruleno==0);
+ /* (1) in ::= stmt */ yytestcase(yyruleno==1);
+ /* (2) in ::= in stmt */ yytestcase(yyruleno==2);
+ /* (3) stmt ::= ENDS */ yytestcase(yyruleno==3);
+ break;
+/********** End reduce actions ************************************************/
+ };
+ assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
+ yygoto = yyRuleInfo[yyruleno].lhs;
+ yysize = yyRuleInfo[yyruleno].nrhs;
+ yypParser->yyidx -= yysize;
+ yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
+ if( yyact <= YY_MAX_SHIFTREDUCE ){
+ if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
+ /* If the reduce action popped at least
+ ** one element off the stack, then we can push the new element back
+ ** onto the stack here, and skip the stack overflow test in yy_shift().
+ ** That gives a significant speed improvement. */
+ if( yysize ){
+ yypParser->yyidx++;
+ yymsp -= yysize-1;
+ yymsp->stateno = (YYACTIONTYPE)yyact;
+ yymsp->major = (YYCODETYPE)yygoto;
+ yymsp->minor = yygotominor;
+ yyTraceShift(yypParser, yyact);
+ }else{
+ yy_shift(yypParser,yyact,yygoto,&yygotominor);
+ }
+ }else{
+ assert( yyact == YY_ACCEPT_ACTION );
+ yy_accept(yypParser);
+ }
+}
+
+/*
+** The following code executes when the parse fails
+*/
+#ifndef YYNOERRORRECOVERY
+static void yy_parse_failed(
+ yyParser *yypParser /* The parser */
+){
+ ParseARG_FETCH;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
+ }
+#endif
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will be executed whenever the
+ ** parser fails */
+/************ Begin %parse_failure code ***************************************/
+/************ End %parse_failure code *****************************************/
+ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+#endif /* YYNOERRORRECOVERY */
+
+/*
+** The following code executes when a syntax error first occurs.
+*/
+static void yy_syntax_error(
+ yyParser *yypParser, /* The parser */
+ int yymajor, /* The major type of the error token */
+ YYMINORTYPE yyminor /* The minor type of the error token */
+){
+ ParseARG_FETCH;
+#define TOKEN (yyminor.yy0)
+/************ Begin %syntax_error code ****************************************/
+#line 14 "grammar.lemon"
+
+ pEval->parseError("Syntax error");
+#line 870 "grammar.c"
+/************ End %syntax_error code ******************************************/
+ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/*
+** The following is executed when the parser accepts
+*/
+static void yy_accept(
+ yyParser *yypParser /* The parser */
+){
+ ParseARG_FETCH;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
+ }
+#endif
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will be executed whenever the
+ ** parser accepts */
+/*********** Begin %parse_accept code *****************************************/
+#line 18 "grammar.lemon"
+
+ pEval->parseOk();
+#line 894 "grammar.c"
+/*********** End %parse_accept code *******************************************/
+ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/* The main parser program.
+** The first argument is a pointer to a structure obtained from
+** "ParseAlloc" which describes the current state of the parser.
+** The second argument is the major token number. The third is
+** the minor token. The fourth optional argument is whatever the
+** user wants (and specified in the grammar) and is available for
+** use by the action routines.
+**
+** Inputs:
+** <ul>
+** <li> A pointer to the parser (an opaque structure.)
+** <li> The major token number.
+** <li> The minor token number.
+** <li> An option argument of a grammar-specified type.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void Parse(
+ void *yyp, /* The parser */
+ int yymajor, /* The major token code number */
+ ParseTOKENTYPE yyminor /* The value for the token */
+ ParseARG_PDECL /* Optional %extra_argument parameter */
+){
+ YYMINORTYPE yyminorunion;
+ int yyact; /* The parser action. */
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
+ int yyendofinput; /* True if we are at the end of input */
+#endif
+#ifdef YYERRORSYMBOL
+ int yyerrorhit = 0; /* True if yymajor has invoked an error */
+#endif
+ yyParser *yypParser; /* The parser */
+
+ /* (re)initialize the parser, if necessary */
+ yypParser = (yyParser*)yyp;
+ if( yypParser->yyidx<0 ){
+#if YYSTACKDEPTH<=0
+ if( yypParser->yystksz <=0 ){
+ /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
+ yyminorunion = yyzerominor;
+ yyStackOverflow(yypParser, &yyminorunion);
+ return;
+ }
+#endif
+ yypParser->yyidx = 0;
+ yypParser->yyerrcnt = -1;
+ yypParser->yystack[0].stateno = 0;
+ yypParser->yystack[0].major = 0;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n",
+ yyTracePrompt);
+ }
+#endif
+ }
+ yyminorunion.yy0 = yyminor;
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
+ yyendofinput = (yymajor==0);
+#endif
+ ParseARG_STORE;
+
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]);
+ }
+#endif
+
+ do{
+ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
+ if( yyact <= YY_MAX_SHIFTREDUCE ){
+ if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
+ yy_shift(yypParser,yyact,yymajor,&yyminorunion);
+ yypParser->yyerrcnt--;
+ yymajor = YYNOCODE;
+ }else if( yyact <= YY_MAX_REDUCE ){
+ yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
+ }else{
+ assert( yyact == YY_ERROR_ACTION );
+#ifdef YYERRORSYMBOL
+ int yymx;
+#endif
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
+ }
+#endif
+#ifdef YYERRORSYMBOL
+ /* A syntax error has occurred.
+ ** The response to an error depends upon whether or not the
+ ** grammar defines an error token "ERROR".
+ **
+ ** This is what we do if the grammar does define ERROR:
+ **
+ ** * Call the %syntax_error function.
+ **
+ ** * Begin popping the stack until we enter a state where
+ ** it is legal to shift the error symbol, then shift
+ ** the error symbol.
+ **
+ ** * Set the error count to three.
+ **
+ ** * Begin accepting and shifting new tokens. No new error
+ ** processing will occur until three tokens have been
+ ** shifted successfully.
+ **
+ */
+ if( yypParser->yyerrcnt<0 ){
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ }
+ yymx = yypParser->yystack[yypParser->yyidx].major;
+ if( yymx==YYERRORSYMBOL || yyerrorhit ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sDiscard input token %s\n",
+ yyTracePrompt,yyTokenName[yymajor]);
+ }
+#endif
+ yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
+ yymajor = YYNOCODE;
+ }else{
+ while(
+ yypParser->yyidx >= 0 &&
+ yymx != YYERRORSYMBOL &&
+ (yyact = yy_find_reduce_action(
+ yypParser->yystack[yypParser->yyidx].stateno,
+ YYERRORSYMBOL)) >= YY_MIN_REDUCE
+ ){
+ yy_pop_parser_stack(yypParser);
+ }
+ if( yypParser->yyidx < 0 || yymajor==0 ){
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ yy_parse_failed(yypParser);
+ yymajor = YYNOCODE;
+ }else if( yymx!=YYERRORSYMBOL ){
+ YYMINORTYPE u2;
+ u2.YYERRSYMDT = 0;
+ yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
+ }
+ }
+ yypParser->yyerrcnt = 3;
+ yyerrorhit = 1;
+#elif defined(YYNOERRORRECOVERY)
+ /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
+ ** do any kind of error recovery. Instead, simply invoke the syntax
+ ** error routine and continue going as if nothing had happened.
+ **
+ ** Applications can set this macro (for example inside %include) if
+ ** they intend to abandon the parse upon the first syntax error seen.
+ */
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ yymajor = YYNOCODE;
+
+#else /* YYERRORSYMBOL is not defined */
+ /* This is what we do if the grammar does not define ERROR:
+ **
+ ** * Report an error message, and throw away the input token.
+ **
+ ** * If the input token is $, then fail the parse.
+ **
+ ** As before, subsequent error messages are suppressed until
+ ** three input tokens have been successfully shifted.
+ */
+ if( yypParser->yyerrcnt<=0 ){
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ }
+ yypParser->yyerrcnt = 3;
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ if( yyendofinput ){
+ yy_parse_failed(yypParser);
+ }
+ yymajor = YYNOCODE;
+#endif
+ }
+ }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ int i;
+ fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
+ for(i=1; i<=yypParser->yyidx; i++)
+ fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ',
+ yyTokenName[yypParser->yystack[i].major]);
+ fprintf(yyTraceFILE,"]\n");
+ }
+#endif
+ return;
+}
diff --git a/common/libeval/grammar.h b/common/libeval/grammar.h
new file mode 100644
index 000000000..60ee42650
--- /dev/null
+++ b/common/libeval/grammar.h
@@ -0,0 +1,12 @@
+#define VAR 1
+#define ASSIGN 2
+#define UNIT 3
+#define SEMCOL 4
+#define PLUS 5
+#define MINUS 6
+#define DIVIDE 7
+#define MULT 8
+#define ENDS 9
+#define VALUE 10
+#define PARENL 11
+#define PARENR 12
diff --git a/common/libeval/grammar.lemon b/common/libeval/grammar.lemon
new file mode 100644
index 000000000..73d09cea2
--- /dev/null
+++ b/common/libeval/grammar.lemon
@@ -0,0 +1,47 @@
+%token_type { numEval::TokenType }
+%extra_argument { NumericEvaluator* pEval }
+
+%nonassoc VAR ASSIGN UNIT SEMCOL.
+%left PLUS MINUS.
+%left DIVIDE MULT.
+
+%include {
+#include <assert.h>
+#include <math.h>
+#include "numeric_evaluator.h"
+}
+
+%syntax_error {
+ pEval->parseError("Syntax error");
+}
+
+%parse_accept {
+ pEval->parseOk();
+}
+
+main ::= in.
+
+in ::= stmt.
+in ::= in stmt.
+
+stmt ::= ENDS.
+stmt ::= expr(A) ENDS. { pEval->parseSetResult(A.valid ? A.dValue : NAN); }
+stmt ::= expr SEMCOL. { pEval->parseSetResult(NAN); }
+
+expr(A) ::= VALUE(B). { A.dValue = B.dValue; A.valid=true; }
+expr(A) ::= VALUE(B) UNIT(C). { A.dValue = B.dValue * C.dValue; A.valid=true; }
+expr(A) ::= MINUS expr(B). { A.dValue = -B.dValue; A.valid=B.valid; }
+expr(A) ::= VAR(B). { A.dValue = pEval->getVar(B.text); A.valid=true; }
+expr(A) ::= VAR(B) ASSIGN expr(C). { pEval->setVar(B.text, C.dValue); A.dValue = C.dValue; A.valid=false; }
+expr(A) ::= expr(B) PLUS expr(C). { A.dValue = B.dValue + C.dValue; A.valid=C.valid; }
+expr(A) ::= expr(B) MINUS expr(C). { A.dValue = B.dValue - C.dValue; A.valid=C.valid; }
+expr(A) ::= expr(B) MULT expr(C). { A.dValue = B.dValue * C.dValue; A.valid=C.valid; }
+expr(A) ::= expr(B) DIVIDE expr(C). {
+ if (C.dValue != 0.0) {
+ A.dValue = B.dValue / C.dValue;
+ }
+ else pEval->parseError("Div by zero");
+ A.valid=C.valid;
+}
+expr(A) ::= PARENL expr(B) PARENR. { A.dValue = B.dValue; A.valid=B.valid; }
+
diff --git a/common/libeval/numeric_evaluator.cpp b/common/libeval/numeric_evaluator.cpp
new file mode 100644
index 000000000..4f7c96065
--- /dev/null
+++ b/common/libeval/numeric_evaluator.cpp
@@ -0,0 +1,302 @@
+/*
+ * numeric_evaluator.cpp
+ *
+ * Created on: Aug 27, 2017
+ * Author: let
+ */
+
+#define TESTMODE 0
+
+#include "numeric_evaluator.h"
+
+#if !TESTMODE
+#include <common.h>
+#else
+#include <unistd.h>
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+namespace numEval
+{
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#endif
+
+#include "grammar.c"
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+} /* namespace numEval */
+
+NumericEvaluator :: NumericEvaluator() : pClParser(0)
+{
+ cClDecSep = '.';
+ bClTextInputStorage = true;
+ init();
+}
+
+NumericEvaluator :: ~NumericEvaluator()
+{
+ numEval::ParseFree(pClParser, free);
+
+ // Allow explicit call to destructor
+ pClParser = nullptr;
+ clear();
+}
+
+void
+NumericEvaluator :: init()
+{
+ if (pClParser == nullptr)
+ pClParser = numEval::ParseAlloc(malloc);
+
+ //numEval::ParseTrace(stdout, "lib");
+
+#if TESTMODE
+ eClUnitDefault = Unit::Metric;
+#else
+ switch (g_UserUnit)
+ {
+ case INCHES : eClUnitDefault = Unit::Inch; break;
+ case MILLIMETRES : eClUnitDefault = Unit::Metric; break;
+ default: eClUnitDefault = Unit::Metric; break;
+ }
+#endif
+}
+
+void
+NumericEvaluator :: clear()
+{
+ free(clToken.token);
+ clToken.token = nullptr;
+ clToken.input = nullptr;
+ bClError = true;
+}
+
+void
+NumericEvaluator :: parse(int token, numEval::TokenType value)
+{
+ numEval::Parse(pClParser, token, value, this);
+}
+
+void
+NumericEvaluator :: parseError(const char* s)
+{
+ bClError = true;
+}
+
+void
+NumericEvaluator :: parseOk()
+{
+ bClError = false;
+ bClParseFinished = true;
+}
+
+void
+NumericEvaluator :: parseSetResult(double val)
+{
+ snprintf(clToken.token, clToken.OutLen, "%g", val);
+}
+
+const char*
+NumericEvaluator :: textInput(const void* pObj) const
+{
+ auto it = clObjMap.find(pObj);
+ if (it != clObjMap.end()) return it->second.c_str();
+
+ return nullptr;
+}
+
+bool
+NumericEvaluator :: process(const char* s)
+{
+ newString(s);
+
+ if (pClParser == nullptr) init();
+ bClParseFinished = false;
+
+ Token tok;
+ numEval::TokenType parseTok;
+ do {
+ tok = getToken();
+ parse(tok.token, tok.value);
+ if (bClParseFinished || tok.token == ENDS) {
+ numEval::Parse(pClParser, 0, parseTok, this);
+ break;
+ }
+ //usleep(200000);
+ } while (tok.token);
+
+ return !bClError;
+}
+
+bool
+NumericEvaluator :: process(const char* s, const void* pObj)
+{
+ if (bClTextInputStorage)
+ clObjMap[pObj] = s;
+ return process(s);
+}
+
+void
+NumericEvaluator :: newString(const char* s)
+{
+ clear();
+ auto len = strlen(s);
+ if (len) {
+ clToken.token = reinterpret_cast<decltype(clToken.token)>(malloc(TokenStat::OutLen+1));
+ clToken.inputLen = len;
+ clToken.pos = 0;
+ clToken.input = s;
+ bClParseFinished = false;
+ }
+}
+
+NumericEvaluator::Token
+NumericEvaluator :: getToken()
+{
+ Token retval;
+ size_t idx;
+
+ retval.token = ENDS;
+ retval.value.dValue = 0;
+
+ if (clToken.token == nullptr) return retval;
+ if (clToken.input == nullptr) return retval;
+ if (clToken.pos >= clToken.inputLen) return retval;
+
+ auto extractNumber = [&idx, this]() {
+ short sepCount = 0;
+ idx = 0;
+ auto ch = clToken.input[clToken.pos];
+ do {
+ if (ch == cClDecSep && sepCount) break;
+ clToken.token[idx++] = ch;
+ if (ch == cClDecSep) sepCount++;
+ ch = clToken.input[++clToken.pos];
+ } while (isdigit(ch) || ch == cClDecSep);
+ clToken.token[idx] = 0;
+ };
+
+ auto checkUnit = [this]() -> Unit {
+ char ch = clToken.input[clToken.pos];
+ if (ch == '"' || ch == 'm') {
+ Unit convertFrom = Unit::Invalid;
+ if (ch == '"') {
+ convertFrom = Unit::Inch;
+ clToken.pos++;
+ }
+ else {
+ // Do not use strcasecmp() as it is not available on all platforms
+ const char* cptr = &clToken.input[clToken.pos];
+ const auto sizeLeft = clToken.inputLen - clToken.pos;
+ if (sizeLeft >= 2) {
+ if (tolower(cptr[1]) == 'm' && !isalnum(cptr[2])) {
+ convertFrom = Unit::Metric;
+ clToken.pos += 2;
+ }
+ else if (sizeLeft >= 3) {
+ if (tolower(cptr[1]) == 'i' && tolower(cptr[2]) == 'l' && !isalnum(cptr[3])) {
+ convertFrom = Unit::Mil;
+ clToken.pos += 3;
+ }
+ }
+ }
+ }
+ return convertFrom;
+ }
+ return Unit::Invalid;
+ };
+
+ char ch;
+ for (;;) {
+ ch = clToken.input[clToken.pos];
+ if (ch == ' ') {
+ clToken.pos++;
+ }
+ else break;
+ }
+
+ Unit convertFrom;
+
+ if (ch == 0) {
+ /* End of input */
+ }
+ else if (isdigit(ch) || ch == cClDecSep) {
+ extractNumber();
+ retval.token = VALUE;
+ retval.value.dValue = atof(clToken.token);
+ }
+ else if ((convertFrom = checkUnit()) != Unit::Invalid) {
+ retval.token = UNIT;
+ if (eClUnitDefault == Unit::Metric)
+ {
+ switch (convertFrom)
+ {
+ case Unit::Inch : retval.value.dValue = 25.4; break;
+ case Unit::Mil : retval.value.dValue = 25.4/1000.0; break;
+ case Unit::Metric : retval.value.dValue = 1.0; break;
+ case Unit::Invalid : break;
+ }
+ }
+ else if (eClUnitDefault == Unit::Inch)
+ {
+ switch (convertFrom)
+ {
+ case Unit::Inch : retval.value.dValue = 1.0; break;
+ case Unit::Mil : retval.value.dValue = 1.0/1000.0; break;
+ case Unit::Metric : retval.value.dValue = 1.0/25.4; break;
+ case Unit::Invalid : break;
+ }
+ }
+ }
+ else if (isalpha(ch)) { // Variable
+ const char* cptr = &clToken.input[clToken.pos];
+ cptr++;
+ while (isalnum(*cptr)) cptr++;
+ retval.token = VAR;
+ size_t bytesToCopy = cptr - &clToken.input[clToken.pos];
+ if (bytesToCopy >= sizeof(retval.value.text)) bytesToCopy = sizeof(retval.value.text)-1;
+ strncpy(retval.value.text, &clToken.input[clToken.pos], bytesToCopy);
+ retval.value.text[bytesToCopy] = 0;
+ clToken.pos += cptr - &clToken.input[clToken.pos];
+ }
+ else {
+ switch (ch) {
+ case '+' : retval.token = PLUS; break;
+ case '-' : retval.token = MINUS; break;
+ case '*' : retval.token = MULT; break;
+ case '/' : retval.token = DIVIDE; break;
+ case '(' : retval.token = PARENL; break;
+ case ')' : retval.token = PARENR; break;
+ case '=' : retval.token = ASSIGN; break;
+ case ';' : retval.token = SEMCOL; break;
+ }
+ clToken.pos++;
+ }
+
+ return retval;
+}
+
+void
+NumericEvaluator :: setVar(const std::string& s, double value)
+{
+ clVarMap[s] = value;
+}
+
+double
+NumericEvaluator :: getVar(const std::string& s)
+{
+ auto result = clVarMap.find(s);
+ if (result != clVarMap.end()) return result->second;
+ return 0.0;
+}
diff --git a/common/libeval/numeric_evaluator.h b/common/libeval/numeric_evaluator.h
new file mode 100644
index 000000000..0718c00ee
--- /dev/null
+++ b/common/libeval/numeric_evaluator.h
@@ -0,0 +1,86 @@
+/*
+ * numeric_evaluator.h
+ *
+ * Created on: Aug 27, 2017
+ * Author: let
+ */
+
+#ifndef NUMERIC_EVALUATOR_H_
+#define NUMERIC_EVALUATOR_H_
+
+#include "grammar.h"
+#include <stddef.h>
+#include <string>
+#include <string>
+#include <map>
+
+namespace numEval
+{
+
+struct TokenType
+{
+ union {
+ double dValue;
+ int iValue;
+ };
+ bool valid;
+ char text[32];
+};
+
+} // namespace numEval
+
+class NumericEvaluator {
+ enum class Unit { Invalid, Metric, Inch, Mil };
+
+public:
+ NumericEvaluator();
+ ~NumericEvaluator();
+
+ void init();
+ void clear();
+ void setDecimalSeparator(char sep);
+ void enableTextInputStorage(bool w) { bClTextInputStorage = w; }
+ void parse(int token, numEval::TokenType value);
+ void parseError(const char* s);
+ void parseOk();
+ void parseSetResult(double);
+ inline bool isValid() const { return !bClError; }
+ inline const char* result() const { return clToken.token; }
+
+ bool process(const char* s);
+ bool process(const char* s, const void* pObj);
+ const char* textInput(const void* pObj) const;
+ void setVar(const std::string&, double value);
+ double getVar(const std::string&);
+ void removeVar(const std::string& s) { clVarMap.erase(s); }
+ void clearVar() { clVarMap.clear(); }
+
+protected:
+ struct Token {
+ int token;
+ numEval::TokenType value;
+ };
+ void newString(const char* s);
+ Token getToken();
+
+private:
+ void* pClParser;
+ struct TokenStat {
+ enum { OutLen=32 };
+ TokenStat() : input(0), token(0), inputLen(0) { /* empty */ }
+ const char* input;
+ char* token;
+ size_t inputLen;
+ size_t pos;
+ } clToken;
+ char cClDecSep;
+ bool bClError;
+ bool bClParseFinished;
+ bool bClTextInputStorage;
+ Unit eClUnitDefault;
+ std::map<const void*, std::string> clObjMap;
+ std::map<std::string, double> clVarMap;
+};
+
+
+#endif /* NUMERIC_EVALUATOR_H_ */
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index 8deba7d43..da2808255 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -41,6 +41,7 @@ include_directories(
../common
../polygon
../common/dialogs
+ ../common/libeval
./exporters
../lib_dxf
./import_dxf
@@ -323,6 +324,7 @@ set( PCBNEW_SRCS
${PCBNEW_MICROWAVE_SRCS}
${PCBNEW_CLASS_SRCS}
${PCBNEW_DIALOGS}
+ ${PCBNEW_LIBEVAL_SRCS}
)
# extra sources from common
diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp
index ea49892cb..d20f6abfb 100644
--- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp
+++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp
@@ -786,3 +786,28 @@ void DIALOG_MODULE_BOARD_EDITOR::Cfg3DPath( wxCommandEvent& event )
if( m_PreviewPane )
m_PreviewPane->SetModelDataIdx( m_LastSelected3DShapeIndex, true );
}
+
+void DIALOG_MODULE_BOARD_EDITOR::OnTextFocusLost(wxFocusEvent& event)
+{
+ wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
+
+ if( obj->GetValue().IsEmpty() )
+ obj->SetValue( "0" );
+
+ if (m_eval.process(obj->GetValue().mb_str(), obj))
+ {
+ obj->SetValue(wxString::FromUTF8(m_eval.result()));
+ }
+
+ event.Skip();
+}
+
+void DIALOG_MODULE_BOARD_EDITOR::OnTextFocusGet(wxFocusEvent& event)
+{
+ wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
+
+ auto oldStr = m_eval.textInput(obj);
+ if (oldStr) obj->SetValue(wxString::FromUTF8(oldStr));
+
+ event.Skip();
+}
diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.h b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.h
index 5e83f03f6..8eb42c724 100644
--- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.h
+++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.h
@@ -30,6 +30,8 @@
#include <dialog_edit_module_for_BoardEditor_base.h>
#include <wx/valnum.h>
+#include <libeval/numeric_evaluator.h>
+
class PANEL_PREV_3D;
class DIALOG_MODULE_BOARD_EDITOR: public DIALOG_MODULE_BOARD_EDITOR_BASE
@@ -49,6 +51,8 @@ private:
wxFloatingPointValidator<double> m_OrientValidator;
double m_OrientValue;
+ NumericEvaluator m_eval;
+
public:
// The dialog can be closed for several reasons.
// they are listed here:
@@ -101,6 +105,9 @@ private:
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
+
+ void OnTextFocusLost( wxFocusEvent& event ) override;
+ void OnTextFocusGet( wxFocusEvent& event ) override;
};
diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp
index 2416808d3..6ad54b457 100644
--- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp
+++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Feb 19 2017)
+// C++ code generated with wxFormBuilder (version Dec 21 2016)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -368,8 +368,18 @@ DIALOG_MODULE_BOARD_EDITOR_BASE::DIALOG_MODULE_BOARD_EDITOR_BASE( wxWindow* pare
m_button4->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnEditReference ), NULL, this );
m_button5->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnEditValue ), NULL, this );
m_OrientCtrl->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::ModuleOrientEvent ), NULL, this );
+ m_ModPositionX->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_ModPositionX->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
+ m_ModPositionY->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_ModPositionY->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
m_buttonExchange->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::ExchangeModule ), NULL, this );
m_buttonModuleEditor->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::GotoModuleEditor ), NULL, this );
+ m_NetClearanceValueCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_NetClearanceValueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderMaskMarginCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderMaskMarginCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderPasteMarginCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderPasteMarginCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
m_3D_ShapeNameListBox->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::On3DShapeNameSelected ), NULL, this );
m_3D_ShapeNameListBox->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::Edit3DShapeFilename ), NULL, this );
m_buttonAdd->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::Add3DShape ), NULL, this );
@@ -385,8 +395,18 @@ DIALOG_MODULE_BOARD_EDITOR_BASE::~DIALOG_MODULE_BOARD_EDITOR_BASE()
m_button4->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnEditReference ), NULL, this );
m_button5->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnEditValue ), NULL, this );
m_OrientCtrl->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::ModuleOrientEvent ), NULL, this );
+ m_ModPositionX->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_ModPositionX->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
+ m_ModPositionY->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_ModPositionY->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
m_buttonExchange->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::ExchangeModule ), NULL, this );
m_buttonModuleEditor->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::GotoModuleEditor ), NULL, this );
+ m_NetClearanceValueCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_NetClearanceValueCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderMaskMarginCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderMaskMarginCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderPasteMarginCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderPasteMarginCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::OnTextFocusGet ), NULL, this );
m_3D_ShapeNameListBox->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::On3DShapeNameSelected ), NULL, this );
m_3D_ShapeNameListBox->Disconnect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::Edit3DShapeFilename ), NULL, this );
m_buttonAdd->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MODULE_BOARD_EDITOR_BASE::Add3DShape ), NULL, this );
diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp
index dfd5b8cf0..51167e158 100644
--- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp
+++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp
@@ -1416,7 +1416,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -1431,7 +1431,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -1673,7 +1673,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -1688,7 +1688,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -3208,7 +3208,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -3223,7 +3223,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -3708,7 +3708,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -3723,7 +3723,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -3965,7 +3965,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -3980,7 +3980,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h
index 51f522972..b290fbe03 100644
--- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h
+++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Feb 19 2017)
+// C++ code generated with wxFormBuilder (version Dec 21 2016)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -119,6 +119,8 @@ class DIALOG_MODULE_BOARD_EDITOR_BASE : public DIALOG_SHIM
virtual void OnEditReference( wxCommandEvent& event ) { event.Skip(); }
virtual void OnEditValue( wxCommandEvent& event ) { event.Skip(); }
virtual void ModuleOrientEvent( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
+ virtual void OnTextFocusGet( wxFocusEvent& event ) { event.Skip(); }
virtual void ExchangeModule( wxCommandEvent& event ) { event.Skip(); }
virtual void GotoModuleEditor( wxCommandEvent& event ) { event.Skip(); }
virtual void On3DShapeNameSelected( wxCommandEvent& event ) { event.Skip(); }
diff --git a/pcbnew/dialogs/dialog_move_exact.cpp b/pcbnew/dialogs/dialog_move_exact.cpp
index b3bc94c56..58407cc70 100644
--- a/pcbnew/dialogs/dialog_move_exact.cpp
+++ b/pcbnew/dialogs/dialog_move_exact.cpp
@@ -337,5 +337,10 @@ void DIALOG_MOVE_EXACT::OnTextFocusLost( wxFocusEvent& event )
if( obj->GetValue().IsEmpty() )
obj->SetValue( "0" );
+ if (m_eval.process(obj->GetValue().mb_str()))
+ {
+ obj->SetValue(wxString::FromUTF8(m_eval.result()));
+ }
+
event.Skip();
}
diff --git a/pcbnew/dialogs/dialog_move_exact.h b/pcbnew/dialogs/dialog_move_exact.h
index 6804aab76..62e6663d0 100644
--- a/pcbnew/dialogs/dialog_move_exact.h
+++ b/pcbnew/dialogs/dialog_move_exact.h
@@ -30,6 +30,8 @@
#include <vector>
#include <dialog_move_exact_base.h>
+#include <libeval/numeric_evaluator.h>
+
enum MOVE_EXACT_ORIGIN
{
RELATIVE_TO_CURRENT_POSITION,
@@ -110,6 +112,8 @@ private:
// Update texts (comments) after changing the coordinates type (polar/cartesian)
void updateDlgTexts( bool aPolar );
+ NumericEvaluator m_eval;
+
/**
* Persistent dialog options
*/
diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp
index 7a184cbb9..ab93cb3e1 100644
--- a/pcbnew/dialogs/dialog_pad_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_properties.cpp
@@ -1361,3 +1361,29 @@ void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
redraw();
}
}
+
+void DIALOG_PAD_PROPERTIES::OnTextFocusLost( wxFocusEvent& event )
+{
+ wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
+
+ if( obj->GetValue().IsEmpty() )
+ obj->SetValue( "0" );
+
+ if (m_eval.process(obj->GetValue().mb_str(), obj))
+ {
+ if (obj != m_ScratchPad)
+ obj->SetValue(wxString::FromUTF8(m_eval.result()));
+ }
+
+ event.Skip();
+}
+
+void DIALOG_PAD_PROPERTIES::OnTextFocusGet( wxFocusEvent& event )
+{
+ wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
+
+ auto oldStr = m_eval.textInput(obj);
+ if (oldStr) obj->SetValue(wxString::FromUTF8(oldStr));
+
+ event.Skip();
+}
diff --git a/pcbnew/dialogs/dialog_pad_properties.h b/pcbnew/dialogs/dialog_pad_properties.h
index 59d341e01..03d20d59e 100644
--- a/pcbnew/dialogs/dialog_pad_properties.h
+++ b/pcbnew/dialogs/dialog_pad_properties.h
@@ -46,7 +46,7 @@
#include <dialog_pad_properties_base.h>
#include <pcb_draw_panel_gal.h>
-
+#include <libeval/numeric_evaluator.h>
/**
* class DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE,
@@ -83,6 +83,8 @@ private:
wxFloatingPointValidator<double> m_OrientValidator;
double m_OrientValue;
+ NumericEvaluator m_eval;
+
private:
void initValues();
bool padValuesOK(); ///< test if all values are acceptable for the pad
@@ -122,6 +124,9 @@ private:
/// Automatically fired from the OK button click.
bool TransferDataFromWindow() override;
bool TransferDataToWindow() override;
+
+ void OnTextFocusLost( wxFocusEvent& event ) override;
+ void OnTextFocusGet( wxFocusEvent& event ) override;
};
#endif // #ifndef _DIALOG_PAD_PROPERTIES_H_
diff --git a/pcbnew/dialogs/dialog_pad_properties_base.cpp b/pcbnew/dialogs/dialog_pad_properties_base.cpp
index 30c2ce3f2..7b70608af 100644
--- a/pcbnew/dialogs/dialog_pad_properties_base.cpp
+++ b/pcbnew/dialogs/dialog_pad_properties_base.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jul 17 2016)
+// C++ code generated with wxFormBuilder (version Sep 2 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -70,7 +70,25 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
fgSizerPadType->Add( m_PadShape, 0, wxALL|wxEXPAND, 5 );
- m_LeftBoxSizer->Add( fgSizerPadType, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
+ m_LeftBoxSizer->Add( fgSizerPadType, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
+
+ wxFlexGridSizer* fgSizer9;
+ fgSizer9 = new wxFlexGridSizer( 1, 2, 0, 0 );
+ fgSizer9->AddGrowableCol( 2 );
+ fgSizer9->AddGrowableRow( 1 );
+ fgSizer9->SetFlexibleDirection( wxBOTH );
+ fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+ fgSizer9->SetMinSize( wxSize( 100,50 ) );
+ m_staticText66 = new wxStaticText( m_panelGeneral, wxID_ANY, _("Scratch"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText66->Wrap( -1 );
+ fgSizer9->Add( m_staticText66, 0, wxALL, 5 );
+
+ m_ScratchPad = new wxTextCtrl( m_panelGeneral, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ fgSizer9->Add( m_ScratchPad, 0, wxALL|wxEXPAND, 5 );
+
+
+ m_LeftBoxSizer->Add( fgSizer9, 1, wxALIGN_LEFT|wxALIGN_RIGHT|wxALL|wxEXPAND, 5 );
wxFlexGridSizer* fgSizerShapeType;
fgSizerShapeType = new wxFlexGridSizer( 0, 3, 0, 0 );
@@ -253,7 +271,7 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
fgSizerShapeType->Add( m_staticTextCornerSizeUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
- m_LeftBoxSizer->Add( fgSizerShapeType, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
+ m_LeftBoxSizer->Add( fgSizerShapeType, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
bGeneralSizer->Add( m_LeftBoxSizer, 3, wxALL|wxEXPAND, 5 );
@@ -599,17 +617,39 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_PadNetNameCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_PadType->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::PadTypeSelected ), NULL, this );
m_PadShape->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPadShapeSelection ), NULL, this );
+ m_ScratchPad->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ScratchPad->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_PadPosition_X_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadPosition_X_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_PadPosition_Y_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadPosition_Y_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ShapeSize_X_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeSize_X_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeSize_X_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_ShapeSize_Y_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeSize_Y_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeSize_Y_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_PadOrient->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::PadOrientEvent ), NULL, this );
m_PadOrientCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_ShapeOffset_X_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeOffset_X_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeOffset_X_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_ShapeOffset_Y_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeOffset_Y_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeOffset_Y_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_LengthPadToDieCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_LengthPadToDieCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ShapeDelta_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeDelta_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeDelta_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_trapDeltaDirChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_tcCornerSizeRatio->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this );
m_DrillShapeCtrl->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnDrillShapeSelected ), NULL, this );
+ m_PadDrill_X_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadDrill_X_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_PadDrill_X_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_PadDrill_Y_Ctrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadDrill_Y_Ctrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_PadDrill_Y_Ctrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_rbCopperLayersSel->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_PadLayerAdhCmp->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
@@ -623,7 +663,18 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_PadLayerDraft->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_PadLayerECO1->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_PadLayerECO2->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
+ m_NetClearanceValueCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_NetClearanceValueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_NetClearanceValueCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_SolderMaskMarginCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderMaskMarginCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderPasteMarginCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderPasteMarginCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderPasteMarginRatioCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ThermalWidthCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ThermalWidthCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ThermalGapCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ThermalGapCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_panelShowPad->Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPaintShowPanel ), NULL, this );
}
@@ -635,17 +686,39 @@ DIALOG_PAD_PROPERTIES_BASE::~DIALOG_PAD_PROPERTIES_BASE()
m_PadNetNameCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_PadType->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::PadTypeSelected ), NULL, this );
m_PadShape->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPadShapeSelection ), NULL, this );
+ m_ScratchPad->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ScratchPad->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_PadPosition_X_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadPosition_X_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_PadPosition_Y_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadPosition_Y_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ShapeSize_X_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeSize_X_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeSize_X_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_ShapeSize_Y_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeSize_Y_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeSize_Y_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_PadOrient->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::PadOrientEvent ), NULL, this );
m_PadOrientCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_ShapeOffset_X_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeOffset_X_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeOffset_X_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_ShapeOffset_Y_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeOffset_Y_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeOffset_Y_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_LengthPadToDieCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_LengthPadToDieCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ShapeDelta_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ShapeDelta_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_ShapeDelta_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_trapDeltaDirChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_tcCornerSizeRatio->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this );
m_DrillShapeCtrl->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnDrillShapeSelected ), NULL, this );
+ m_PadDrill_X_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadDrill_X_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_PadDrill_X_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_PadDrill_Y_Ctrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_PadDrill_Y_Ctrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_PadDrill_Y_Ctrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_rbCopperLayersSel->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_PadLayerAdhCmp->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
@@ -659,7 +732,18 @@ DIALOG_PAD_PROPERTIES_BASE::~DIALOG_PAD_PROPERTIES_BASE()
m_PadLayerDraft->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_PadLayerECO1->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_PadLayerECO2->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
+ m_NetClearanceValueCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_NetClearanceValueCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_NetClearanceValueCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
+ m_SolderMaskMarginCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderMaskMarginCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderPasteMarginCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_SolderPasteMarginCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_SolderPasteMarginRatioCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ThermalWidthCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ThermalWidthCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
+ m_ThermalGapCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusLost ), NULL, this );
+ m_ThermalGapCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnTextFocusGet ), NULL, this );
m_panelShowPad->Disconnect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPaintShowPanel ), NULL, this );
}
diff --git a/pcbnew/dialogs/dialog_pad_properties_base.fbp b/pcbnew/dialogs/dialog_pad_properties_base.fbp
index 559968212..075c7163f 100644
--- a/pcbnew/dialogs/dialog_pad_properties_base.fbp
+++ b/pcbnew/dialogs/dialog_pad_properties_base.fbp
@@ -44,7 +44,7 @@
<property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_PAD_PROPERTIES_BASE</property>
<property name="pos"></property>
- <property name="size">785,659</property>
+ <property name="size">785,764</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Pad Properties</property>
@@ -267,18 +267,18 @@
<property name="name">bGeneralSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
- <object class="sizeritem" expanded="0">
+ <object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">3</property>
- <object class="wxBoxSizer" expanded="0">
+ <object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">m_LeftBoxSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
- <object class="sizeritem" expanded="0">
+ <object class="sizeritem" expanded="1">
<property name="border">5</property>
- <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
+ <property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
<property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="0">
<property name="cols">2</property>
@@ -984,11 +984,203 @@
</object>
</object>
</object>
- <object class="sizeritem" expanded="0">
+ <object class="sizeritem" expanded="1">
<property name="border">5</property>
- <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND</property>
+ <property name="flag">wxALIGN_LEFT|wxALIGN_RIGHT|wxALL|wxEXPAND</property>
+ <property name="proportion">1</property>
+ <object class="wxFlexGridSizer" expanded="1">
+ <property name="cols">2</property>
+ <property name="flexible_direction">wxBOTH</property>
+ <property name="growablecols">2</property>
+ <property name="growablerows">1</property>
+ <property name="hgap">0</property>
+ <property name="minimum_size">100,50</property>
+ <property name="name">fgSizer9</property>
+ <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
+ <property name="permission">none</property>
+ <property name="rows">1</property>
+ <property name="vgap">0</property>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">0</property>
+ <object class="wxStaticText" expanded="1">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer"></property>
+ <property name="aui_name"></property>
+ <property name="aui_position"></property>
+ <property name="aui_row"></property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="default_pane">0</property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">Scratch</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_staticText66</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <property name="wrap">-1</property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus"></event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALL|wxEXPAND</property>
+ <property name="proportion">0</property>
+ <object class="wxTextCtrl" expanded="1">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer"></property>
+ <property name="aui_name"></property>
+ <property name="aui_position"></property>
+ <property name="aui_row"></property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="default_pane">0</property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="maxlength"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_ScratchPad</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="value"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus">OnTextFocusLost</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">OnTextFocusGet</event>
+ <event name="OnSize"></event>
+ <event name="OnText"></event>
+ <event name="OnTextEnter"></event>
+ <event name="OnTextMaxLen"></event>
+ <event name="OnTextURL"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
- <object class="wxFlexGridSizer" expanded="0">
+ <object class="wxFlexGridSizer" expanded="1">
<property name="cols">3</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property>
@@ -1150,7 +1342,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -1165,7 +1357,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -1407,7 +1599,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -1422,7 +1614,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -1664,7 +1856,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -1679,7 +1871,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -1921,7 +2113,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -1936,7 +2128,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -2282,11 +2474,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
- <object class="spacer" expanded="1">
+ <object class="spacer" expanded="0">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
@@ -2616,7 +2808,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -2631,7 +2823,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -2873,7 +3065,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -2888,7 +3080,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -3130,7 +3322,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -3145,7 +3337,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -3237,11 +3429,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticLine" expanded="1">
+ <object class="wxStaticLine" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -3318,11 +3510,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticLine" expanded="1">
+ <object class="wxStaticLine" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -3399,11 +3591,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticLine" expanded="1">
+ <object class="wxStaticLine" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -3630,7 +3822,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -3645,7 +3837,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -3908,21 +4100,21 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
- <object class="spacer" expanded="1">
+ <object class="spacer" expanded="0">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticLine" expanded="1">
+ <object class="wxStaticLine" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -3999,11 +4191,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticLine" expanded="1">
+ <object class="wxStaticLine" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4080,11 +4272,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticLine" expanded="1">
+ <object class="wxStaticLine" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4161,11 +4353,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
- <object class="wxStaticText" expanded="1">
+ <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4244,11 +4436,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT</property>
<property name="proportion">0</property>
- <object class="wxTextCtrl" expanded="1">
+ <object class="wxTextCtrl" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4335,11 +4527,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
- <object class="wxStaticText" expanded="1">
+ <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4418,11 +4610,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticText" expanded="1">
+ <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4501,11 +4693,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
- <object class="wxStaticText" expanded="1">
+ <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -4584,11 +4776,11 @@
<event name="OnUpdateUI"></event>
</object>
</object>
- <object class="sizeritem" expanded="1">
+ <object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
- <object class="wxStaticText" expanded="1">
+ <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -5113,7 +5305,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -5128,7 +5320,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -5370,7 +5562,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -5385,7 +5577,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -7302,7 +7494,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -7317,7 +7509,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText">OnValuesChanged</event>
<event name="OnTextEnter"></event>
@@ -7559,7 +7751,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -7574,7 +7766,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -7816,7 +8008,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -7831,7 +8023,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -8088,7 +8280,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -8617,7 +8809,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -8632,7 +8824,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
@@ -8874,7 +9066,7 @@
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
- <event name="OnKillFocus"></event>
+ <event name="OnKillFocus">OnTextFocusLost</event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
@@ -8889,7 +9081,7 @@
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
- <event name="OnSetFocus"></event>
+ <event name="OnSetFocus">OnTextFocusGet</event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
diff --git a/pcbnew/dialogs/dialog_pad_properties_base.h b/pcbnew/dialogs/dialog_pad_properties_base.h
index b35e18b32..69931742f 100644
--- a/pcbnew/dialogs/dialog_pad_properties_base.h
+++ b/pcbnew/dialogs/dialog_pad_properties_base.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jul 17 2016)
+// C++ code generated with wxFormBuilder (version Sep 2 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -63,6 +63,8 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM
wxChoice* m_PadType;
wxStaticText* m_staticText45;
wxChoice* m_PadShape;
+ wxStaticText* m_staticText66;
+ wxTextCtrl* m_ScratchPad;
wxStaticText* m_staticText4;
wxTextCtrl* m_PadPosition_X_Ctrl;
wxStaticText* m_PadPosX_Unit;
@@ -168,6 +170,8 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM
virtual void OnValuesChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void PadTypeSelected( wxCommandEvent& event ) { event.Skip(); }
virtual void OnPadShapeSelection( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
+ virtual void OnTextFocusGet( wxFocusEvent& event ) { event.Skip(); }
virtual void PadOrientEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSetLayers( wxCommandEvent& event ) { event.Skip(); }
virtual void onCornerSizePercentChange( wxCommandEvent& event ) { event.Skip(); }
@@ -177,7 +181,7 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM
public:
- DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_DIALOG_EDIT_PAD, const wxString& title = _("Pad Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 785,659 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSUNKEN_BORDER );
+ DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_DIALOG_EDIT_PAD, const wxString& title = _("Pad Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 785,764 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSUNKEN_BORDER );
~DIALOG_PAD_PROPERTIES_BASE();
};
diff --git a/pcbnew/dialogs/dialog_position_relative.cpp b/pcbnew/dialogs/dialog_position_relative.cpp
index e094a225b..58009c748 100644
--- a/pcbnew/dialogs/dialog_position_relative.cpp
+++ b/pcbnew/dialogs/dialog_position_relative.cpp
@@ -196,6 +196,7 @@ void DIALOG_POSITION_RELATIVE::UpdateAnchor( BOARD_ITEM* aBoardItem )
void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event )
{
+ updateEntryFields();
m_rotation = DoubleValueFromString( DEGREES, m_rotEntry->GetValue() );
// for the output, we only deliver a Cartesian vector
@@ -225,5 +226,18 @@ void DIALOG_POSITION_RELATIVE::OnTextFocusLost( wxFocusEvent& event )
if( obj->GetValue().IsEmpty() )
obj->SetValue( "0" );
+ if (m_eval.process(obj->GetValue().mb_str()))
+ {
+ obj->SetValue(wxString::FromUTF8(m_eval.result()));
+ }
+
event.Skip();
}
+
+void DIALOG_POSITION_RELATIVE::updateEntryFields()
+{
+ if (m_eval.process(m_xEntry->GetValue().mb_str()))
+ {
+ m_xEntry->SetValue(wxString::FromUTF8(m_eval.result()));
+ }
+}
diff --git a/pcbnew/dialogs/dialog_position_relative.h b/pcbnew/dialogs/dialog_position_relative.h
index 2adaf0c0c..5c7c33649 100644
--- a/pcbnew/dialogs/dialog_position_relative.h
+++ b/pcbnew/dialogs/dialog_position_relative.h
@@ -31,6 +31,8 @@
#include <tool/tool_manager.h>
#include "tools/position_relative_tool.h"
+#include <libeval/numeric_evaluator.h>
+
class DIALOG_POSITION_RELATIVE : public DIALOG_POSITION_RELATIVE_BASE
{
private:
@@ -80,6 +82,10 @@ private:
// Update texts (comments) after changing the coordinates type (polar/cartesian)
void updateDlgTexts( bool aPolar );
+ void updateEntryFields();
+
+ NumericEvaluator m_eval;
+
/**
* Persistent dialog options
*/
--
2.14.1
Follow ups
References