mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Implement unique IDs and card linking
This commit is contained in:
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
project(magicseteditor VERSION 2.5.8)
|
project(magicseteditor VERSION 2.6.0)
|
||||||
|
|
||||||
add_definitions(-DUNOFFICIAL_BUILD)
|
add_definitions(-DUNOFFICIAL_BUILD)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
@@ -28,7 +29,7 @@ endif()
|
|||||||
|
|
||||||
# You will most likely get a message about being unable to open hunspell-1.7.lib because pkgconf forgets to add the actual path to
|
# You will most likely get a message about being unable to open hunspell-1.7.lib because pkgconf forgets to add the actual path to
|
||||||
# HUNSPELL_LIBRARIES. If so, uncomment the below line and point it to the correct vcpkg root folder/library.
|
# HUNSPELL_LIBRARIES. If so, uncomment the below line and point it to the correct vcpkg root folder/library.
|
||||||
#set(HUNSPELL_LIBRARIES "C:\\PATH\\TO\\ROOT\\vcpkg\\installed\\${VCPKG_TARGET_TRIPLET}\\lib\\hunspell-1.7.lib")
|
set(HUNSPELL_LIBRARIES "C:\\src\\vcpkg\\installed\\${VCPKG_TARGET_TRIPLET}\\lib\\hunspell-1.7.lib")
|
||||||
message("-- Does this have a full path? If not, and it's just a file name, it's broken: Found Hunspell at ${HUNSPELL_LIBRARIES}")
|
message("-- Does this have a full path? If not, and it's just a file name, it's broken: Found Hunspell at ${HUNSPELL_LIBRARIES}")
|
||||||
|
|
||||||
include_directories("${PROJECT_BINARY_DIR}/src")
|
include_directories("${PROJECT_BINARY_DIR}/src")
|
||||||
|
|||||||
+1
-1
@@ -74,4 +74,4 @@
|
|||||||
"inheritEnvironments": [ "msvc_x86" ]
|
"inheritEnvironments": [ "msvc_x86" ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+60
-60
@@ -322,63 +322,63 @@ POSSIBILITY OF SUCH DAMAGES.
|
|||||||
|
|
||||||
==END OF TERMS AND CONDITIONS==
|
==END OF TERMS AND CONDITIONS==
|
||||||
|
|
||||||
|
|
||||||
==<a NAME="SEC4" HREF="#TOC4">How to Apply These Terms to Your New Programs</a>==
|
==<a NAME="SEC4" HREF="#TOC4">How to Apply These Terms to Your New Programs</a>==
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
If you develop a new program, and you want it to be of the greatest
|
||||||
possible use to the public, the best way to achieve this is to make it
|
possible use to the public, the best way to achieve this is to make it
|
||||||
free software which everyone can redistribute and change under these terms.
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
To do so, attach the following notices to the program. It is safest
|
||||||
to attach them to the start of each source file to most effectively
|
to attach them to the start of each source file to most effectively
|
||||||
convey the exclusion of warranty; and each file should have at least
|
convey the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
] <one line to give the program's name and a brief idea of what it does.>
|
] <one line to give the program's name and a brief idea of what it does.>
|
||||||
] Copyright (C) <year> <name of author>
|
] Copyright (C) <year> <name of author>
|
||||||
]
|
]
|
||||||
] This program is free software; you can redistribute it and/or modify
|
] This program is free software; you can redistribute it and/or modify
|
||||||
] it under the terms of the GNU General Public License as published by
|
] it under the terms of the GNU General Public License as published by
|
||||||
] the Free Software Foundation; either version 2 of the License, or
|
] the Free Software Foundation; either version 2 of the License, or
|
||||||
] (at your option) any later version.
|
] (at your option) any later version.
|
||||||
]
|
]
|
||||||
] This program is distributed in the hope that it will be useful,
|
] This program is distributed in the hope that it will be useful,
|
||||||
] but WITHOUT ANY WARRANTY; without even the implied warranty of
|
] but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
] MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
] MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
] GNU General Public License for more details.
|
] GNU General Public License for more details.
|
||||||
]
|
]
|
||||||
] You should have received a copy of the GNU General Public License
|
] You should have received a copy of the GNU General Public License
|
||||||
] along with this program; if not, write to the Free Software
|
] along with this program; if not, write to the Free Software
|
||||||
] Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
] Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
If the program is interactive, make it output a short notice like this
|
||||||
when it starts in an interactive mode:
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
] Gnomovision version 69, Copyright (C) year name of author
|
] Gnomovision version 69, Copyright (C) year name of author
|
||||||
] Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
] Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
] This is free software, and you are welcome to redistribute it
|
] This is free software, and you are welcome to redistribute it
|
||||||
] under certain conditions; type `show c' for details.
|
] under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
parts of the General Public License. Of course, the commands you use may
|
parts of the General Public License. Of course, the commands you use may
|
||||||
be called something other than `show w' and `show c'; they could even be
|
be called something other than `show w' and `show c'; they could even be
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
You should also get your employer (if you work as a programmer) or your
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
necessary. Here is a sample; alter the names:
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
] Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
] Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
] `Gnomovision' (which makes passes at compilers) written by James Hacker.
|
] `Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
]
|
]
|
||||||
] <signature of Ty Coon>, 1 April 1989
|
] <signature of Ty Coon>, 1 April 1989
|
||||||
] Ty Coon, President of Vice
|
] Ty Coon, President of Vice
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
This General Public License does not permit incorporating your program into
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
consider it more useful to permit linking proprietary applications with the
|
consider it more useful to permit linking proprietary applications with the
|
||||||
library. If this is what you want to do, use the GNU Library General
|
library. If this is what you want to do, use the GNU Library General
|
||||||
Public License instead of this License.
|
Public License instead of this License.
|
||||||
|
|||||||
+7
-7
@@ -33,13 +33,13 @@ A heirachical file can contain a reference to another file:
|
|||||||
Where filename must be an absolute or relative [[type:filename]].
|
Where filename must be an absolute or relative [[type:filename]].
|
||||||
|
|
||||||
That file is included literally into the current one; except for indentation, the included file never escapes from the level the 'include file' line is on.
|
That file is included literally into the current one; except for indentation, the included file never escapes from the level the 'include file' line is on.
|
||||||
|
|
||||||
If the file to be included can vary depending on the locale that is selected, use:
|
If the file to be included can vary depending on the locale that is selected, use:
|
||||||
>>>include localized file: <em>filename</em>
|
>>>include localized file: <em>filename</em>
|
||||||
|
|
||||||
MSE will take the filename and add "_" followed by the name of the currently selected locale at the end of it.
|
MSE will take the filename and add "_" followed by the name of the currently selected locale at the end of it.
|
||||||
So for example, if the locale used is the folder "en.mse-locale", the file that will be included is "filename_en"
|
So for example, if the locale used is the folder "en.mse-locale", the file that will be included is "filename_en"
|
||||||
You must provide a version of the file for each locale found in the data folder, even if it is simply a copy of the english one.
|
You must provide a version of the file for each locale found in the data folder, even if it is simply a copy of the english one.
|
||||||
|
|
||||||
--Example--
|
--Example--
|
||||||
For example, a [[type:set]] might look like this:
|
For example, a [[type:set]] might look like this:
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ Function: crop
|
|||||||
|
|
||||||
Shrink an image by cutting off some of the image, starting at the position denoted by the offsets. The resulting image size is specified in the parameters.
|
Shrink an image by cutting off some of the image, starting at the position denoted by the offsets. The resulting image size is specified in the parameters.
|
||||||
|
|
||||||
|
Resulting image can be bigger than the original, if offset_x or offset_y are negative, or if width or height are bigger than the original width and height.
|
||||||
|
|
||||||
--Parameters--
|
--Parameters--
|
||||||
! Parameter Type Description
|
! Parameter Type Description
|
||||||
| @input@ [[type:image]] Image to enlarge
|
| @input@ [[type:image]] Image to enlarge
|
||||||
| @height@ [[type:double]] Height of the resulting image
|
| @height@ [[type:double]] Height of the resulting image, in pixels
|
||||||
| @width@ [[type:double]] Width of the resulting image
|
| @width@ [[type:double]] Width of the resulting image, in pixels
|
||||||
| @offset_x@ [[type:double]] Offset of crop, horizontally
|
| @offset_x@ [[type:double]] Offset of crop, horizontally, in pixels
|
||||||
| @offset_y@ [[type:double]] Offset of crop, vertically
|
| @offset_y@ [[type:double]] Offset of crop, vertically, in pixels
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Function: dimensions_of
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> dimensions_of(input: image)
|
||||||
|
|
||||||
|
Returns an array containing the width and height of the image in pixels.
|
||||||
|
|
||||||
|
--Parameters--
|
||||||
|
! Parameter Type Description
|
||||||
|
| @input@ [[type:image]] Image to whos dimensions we want.
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
Function: get_card_from_link
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> get_card_from_link(card: card, "link type")
|
||||||
|
|
||||||
|
Inspects a given [[type:card]]'s links to find one of the given type, and returns the linked card.
|
||||||
|
Returns nil if no card was found.
|
||||||
|
|
||||||
|
--Parameters--
|
||||||
|
! Parameter Type Description
|
||||||
|
| @input@ [[type:string]] The type of link we want to find.
|
||||||
|
| @card@ [[type:card]] The card whose links we'll inspect.
|
||||||
|
| @set@ [[type:set]] The set in which to look. This can be omited since 'set' is a predefined variable.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Function: get_card_from_uid
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> get_card_from_uid(input: "uid")
|
||||||
|
|
||||||
|
Returns the [[type:card]] with the given uid inside the set.
|
||||||
|
Returns nil if no card was found.
|
||||||
|
|
||||||
|
--Parameters--
|
||||||
|
! Parameter Type Description
|
||||||
|
| @input@ [[type:string]] The uid of the card we want to retrieve.
|
||||||
|
| @set@ [[type:set]] The set in which to look. This can be omited since 'set' is a predefined variable.
|
||||||
@@ -5,12 +5,12 @@ Function: get_card_styling
|
|||||||
|
|
||||||
Get the styling data of a [[type:card]].
|
Get the styling data of a [[type:card]].
|
||||||
|
|
||||||
This is for use in exporter scripts. In card scripts, use the "styling" predefined variable instead.
|
This is for use in exporter scripts. In card scripts, use the 'styling' predefined variable instead.
|
||||||
|
|
||||||
--Parameters--
|
--Parameters--
|
||||||
! Parameter Type Description
|
! Parameter Type Description
|
||||||
| @input@ [[type:card]] The card you want to retrieve the styling data from.
|
| @input@ [[type:card]] The card you want to retrieve the styling data from.
|
||||||
| @set@ [[type:set]] The set the card belongs to. In an exporter script, this can be omited since "set" is a predefined variable.
|
| @set@ [[type:set]] The set the card belongs to. In an exporter script, this can be omited since 'set' is a predefined variable.
|
||||||
|
|
||||||
--Examples--
|
--Examples--
|
||||||
> # Retrieve the value "is foil" from the card's styling options
|
> # Retrieve the value "is foil" from the card's styling options
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Function: get_mse_locale
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> get_mse_locale()
|
||||||
|
|
||||||
|
Returns the name of the currently selected locale folder.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Function: has_link
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> has_link(card: card, "link type")
|
||||||
|
|
||||||
|
Inspects a given [[type:card]]'s links to find one of the given type.
|
||||||
|
Returns true if such a link was found, false otherwise.
|
||||||
|
|
||||||
|
Note that this function does not check if the linked card exists in the set. For that, use get_card_from_link.
|
||||||
|
|
||||||
|
--Parameters--
|
||||||
|
! Parameter Type Description
|
||||||
|
| @input@ [[type:string]] The type of link we want to find.
|
||||||
|
| @card@ [[type:card]] The card whose links we'll inspect.
|
||||||
@@ -97,6 +97,8 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
| [[fun:flip_vertical]] Flip an image vertically.
|
| [[fun:flip_vertical]] Flip an image vertically.
|
||||||
| [[fun:rotate_image]] Rotate an image.
|
| [[fun:rotate_image]] Rotate an image.
|
||||||
| [[fun:drop_shadow]] Add a drop shadow to an image.
|
| [[fun:drop_shadow]] Add a drop shadow to an image.
|
||||||
|
| [[fun:insert_image]] Insert an image inside another.
|
||||||
|
| [[fun:dimensions_of]] Get the width and height of an image.
|
||||||
| [[fun:symbol_variation]] Render a variation of a [[type:symbol]].
|
| [[fun:symbol_variation]] Render a variation of a [[type:symbol]].
|
||||||
| [[fun:import_image]] Load an image from outside the data folder.
|
| [[fun:import_image]] Load an image from outside the data folder.
|
||||||
| [[fun:built_in_image]] Return an image built into the program.
|
| [[fun:built_in_image]] Return an image built into the program.
|
||||||
@@ -106,6 +108,9 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
| [[fun:add_card_to_set]] Add a [[type:card]] to a [[type:set]].
|
| [[fun:add_card_to_set]] Add a [[type:card]] to a [[type:set]].
|
||||||
| [[fun:get_card_styling]] Get the styling data of a [[type:card]].
|
| [[fun:get_card_styling]] Get the styling data of a [[type:card]].
|
||||||
| [[fun:get_card_stylesheet]] Get the stylesheet of a [[type:card]].
|
| [[fun:get_card_stylesheet]] Get the stylesheet of a [[type:card]].
|
||||||
|
| [[fun:get_card_from_uid]] Find the [[type:card]] with the given uid.
|
||||||
|
| [[fun:get_card_from_link]] Find a [[type:card]] that has the given link type to the given [[type:card]].
|
||||||
|
| [[fun:has_link]] Determine if the given the given [[type:card]] has a link of the given type.
|
||||||
|
|
||||||
! HTML export <<<
|
! HTML export <<<
|
||||||
| [[fun:to_html]] Convert [[type:tagged text]] to html.
|
| [[fun:to_html]] Convert [[type:tagged text]] to html.
|
||||||
@@ -118,6 +123,7 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
|
|
||||||
! Other functions <<<
|
! Other functions <<<
|
||||||
| [[fun:get_mse_version]] Get the MSE app version.
|
| [[fun:get_mse_version]] Get the MSE app version.
|
||||||
|
| [[fun:get_mse_locale]] Get the name of the currently selected locale.
|
||||||
| [[fun:get_mse_path]] Get the MSE app folder absolute path.
|
| [[fun:get_mse_path]] Get the MSE app folder absolute path.
|
||||||
| [[fun:trace]] Output a message for debugging purposes.
|
| [[fun:trace]] Output a message for debugging purposes.
|
||||||
| [[fun:assert]] Check a condition for debugging purposes.
|
| [[fun:assert]] Check a condition for debugging purposes.
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Function: insert_image
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> insert_image(base_image: image, inserted_image: image, offset_x: coordinate, offset_y: coordinate, background_color: color)
|
||||||
|
|
||||||
|
Insert an image inside another image.
|
||||||
|
|
||||||
|
The inserted image can be put outside the bounds of the base image. The resulting image will be widened accordingly.
|
||||||
|
|
||||||
|
--Parameters--
|
||||||
|
! Parameter Type Description
|
||||||
|
| @base_image@ [[type:image]] Image that serves as the canvas
|
||||||
|
| @inserted_image@ [[type:image]] Image inserted on top of the base image
|
||||||
|
| @offset_x@ [[type:double]] Offset of insertion, horizontally, in pixels
|
||||||
|
| @offset_y@ [[type:double]] Offset of insertion, vertically, in pixels
|
||||||
|
| @background_color@ [[type:color]] Background color, optional, defaults to transparent
|
||||||
|
|
||||||
@@ -9,8 +9,8 @@ Aside from the [[fun:index|built in functions]] the following variables are prov
|
|||||||
The current stylesheet
|
The current stylesheet
|
||||||
| @card@ [[type:card]] not in @init script@s or when exporting
|
| @card@ [[type:card]] not in @init script@s or when exporting
|
||||||
The current card.
|
The current card.
|
||||||
| @card_style@ [[type:indexmap]] of [[type:style]]s where @card@ is available Style properties for the current card, the same as @stylesheet.card_style@.
|
| @card_style@ [[type:indexmap]] of [[type:style]]s where @card@ is available Style properties for the current card, the same as @stylesheet.card_style@.
|
||||||
| @extra_card@ [[type:indexmap]] of [[type:value]]s field values for the current card as defined by the stylesheet.
|
| @extra_card@ [[type:indexmap]] of [[type:value]]s field values for the current card as defined by the stylesheet.
|
||||||
| @extra_card_style@ [[type:indexmap]] of [[type:style]] where @card@ is available Style properties for the current card as added by the stylesheet.
|
| @extra_card_style@ [[type:indexmap]] of [[type:style]] where @card@ is available Style properties for the current card as added by the stylesheet.
|
||||||
| @styling@ [[type:indexmap]] of [[type:value]]s where @card@ is available Styling options for the stylesheet/card.
|
| @styling@ [[type:indexmap]] of [[type:value]]s where @card@ is available Styling options for the stylesheet/card.
|
||||||
| @value@ [[type:value]] when evaluating a [[type:field]]'s @script@ or @default@ script Current value in the field.
|
| @value@ [[type:value]] when evaluating a [[type:field]]'s @script@ or @default@ script Current value in the field.
|
||||||
|
|||||||
+5
-5
@@ -43,9 +43,9 @@ Fields are part of the [[file:style triangle]]:
|
|||||||
| @card list name@ [[type:localized string]] field name Alternate name to use for the card list, for example an abbreviation.
|
| @card list name@ [[type:localized string]] field name Alternate name to use for the card list, for example an abbreviation.
|
||||||
| @card list alignment@ [[type:alignment]] @left@ Alignment of the card list column.
|
| @card list alignment@ [[type:alignment]] @left@ Alignment of the card list column.
|
||||||
| @sort script@ [[type:script]] Alternate way to sort the card list when using this column to sort the list.
|
| @sort script@ [[type:script]] Alternate way to sort the card list when using this column to sort the list.
|
||||||
| @import script@ [[type:script]] Script applied to the value given when creating a card with the new_card function. The script may return a map from field names to values.
|
| @import script@ [[type:script]] Script applied to the value given when creating a card with the new_card function. The script may return a map from field names to values.
|
||||||
For example, the pt field should not be initialized directly, since it is a combination of the power field and toughness field.
|
For example, the pt field should not be initialized directly, since it is a combination of the power field and toughness field.
|
||||||
So if a value is given for pt, it must be redirected to power and toughness like so: {split := split_text(value, match:"/"); [power:split[0], toughness:split[1]]}.
|
So if a value is given for pt, it must be redirected to power and toughness like so: {split := split_text(value, match:"/"); [power:split[0], toughness:split[1]]}.
|
||||||
Use the make_map function to dynamically create maps.
|
Use the make_map function to dynamically create maps.
|
||||||
|
|
||||||
The @type@ determines what values of this field contain:
|
The @type@ determines what values of this field contain:
|
||||||
@@ -85,8 +85,8 @@ Additional properties are available, depending on the type of field:
|
|||||||
These choices must appear in the same order as they do in the @choices@ property.
|
These choices must appear in the same order as they do in the @choices@ property.
|
||||||
|
|
||||||
| @"boolean"@ ''A boolean field is a choice field with the choices @"yes"@ and @"no"@.'' <<< <<< <<<
|
| @"boolean"@ ''A boolean field is a choice field with the choices @"yes"@ and @"no"@.'' <<< <<< <<<
|
||||||
|
|
||||||
| @"slider"@ ''A slider field is a choice field where the choices are all numbers.'' <<< <<< <<<
|
| @"slider"@ ''A slider field is a choice field where the choices are all numbers.'' <<< <<< <<<
|
||||||
| ^^^ @script@ [[type:script]] Script to apply to values of this field after each change.<br/>
|
| ^^^ @script@ [[type:script]] Script to apply to values of this field after each change.<br/>
|
||||||
If the script evaluates to a constant (i.e. doesn't use @value@) then values in this field can effectively not be edited.
|
If the script evaluates to a constant (i.e. doesn't use @value@) then values in this field can effectively not be edited.
|
||||||
| ^^^ @default@ [[type:script]] Script to determine the value when it is in the default state (not edited).
|
| ^^^ @default@ [[type:script]] Script to determine the value when it is in the default state (not edited).
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -47,6 +47,8 @@ tool/no_auto IMAGE "tool/no_auto.png"
|
|||||||
tool/card_add IMAGE "tool/card_add.png"
|
tool/card_add IMAGE "tool/card_add.png"
|
||||||
tool/card_add_multiple IMAGE "tool/card_add_multiple.png"
|
tool/card_add_multiple IMAGE "tool/card_add_multiple.png"
|
||||||
tool/card_del IMAGE "tool/card_del.png"
|
tool/card_del IMAGE "tool/card_del.png"
|
||||||
|
tool/card_link IMAGE "tool/card_link.png"
|
||||||
|
tool/card_copy IMAGE "tool/card_copy.png"
|
||||||
tool/card_rotate IMAGE "tool/card_rotate.png"
|
tool/card_rotate IMAGE "tool/card_rotate.png"
|
||||||
tool/card_rotate_0 IMAGE "tool/card_rotate_0.png"
|
tool/card_rotate_0 IMAGE "tool/card_rotate_0.png"
|
||||||
tool/card_rotate_90 IMAGE "tool/card_rotate_90.png"
|
tool/card_rotate_90 IMAGE "tool/card_rotate_90.png"
|
||||||
|
|||||||
+83
-2
@@ -13,6 +13,7 @@
|
|||||||
#include <data/pack.hpp>
|
#include <data/pack.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
|
#include <util/uid.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Add card
|
// ----------------------------------------------------------------------------- : Add card
|
||||||
|
|
||||||
@@ -36,10 +37,53 @@ String AddCardAction::getName(bool to_undo) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddCardAction::perform(bool to_undo) {
|
void AddCardAction::perform(bool to_undo) {
|
||||||
|
// If we are adding cards, resolve any uid conflicts
|
||||||
|
// (If we are re-adding cards, from a remove undo, there shouldn't be any uid conflicts)
|
||||||
|
// We always assume uid conflicts occur because a card was copy-pasted into the same set,
|
||||||
|
// and never because two different cards randomly got assigned the same uid
|
||||||
|
if (action.adding && !to_undo) {
|
||||||
|
// Tally existing unique ids
|
||||||
|
unordered_map<String, CardP> all_existing_uids;
|
||||||
|
FOR_EACH(card, set.cards) {
|
||||||
|
all_existing_uids.insert({ card->uid, card });
|
||||||
|
}
|
||||||
|
// Tally added unique ids
|
||||||
|
unordered_map<String, CardP> all_added_uids;
|
||||||
|
for (size_t pos = 0; pos < action.steps.size(); ++pos) {
|
||||||
|
CardP card = action.steps[pos].item;
|
||||||
|
all_added_uids.insert({ card->uid, card });
|
||||||
|
}
|
||||||
|
FOR_EACH(added_pair, all_added_uids) {
|
||||||
|
String old_uid = added_pair.first;
|
||||||
|
CardP added_card = added_pair.second;
|
||||||
|
// Assign new unique ids
|
||||||
|
if (all_existing_uids.find(old_uid) != all_existing_uids.end()) {
|
||||||
|
String new_uid = generate_uid();
|
||||||
|
added_card->uid = new_uid;
|
||||||
|
all_added_uids.insert({ new_uid, added_card });
|
||||||
|
// Update links on linked cards
|
||||||
|
OTHER_LINKED_PAIRS(linked_pairs, added_card);
|
||||||
|
FOR_EACH(linked_pair, linked_pairs) {
|
||||||
|
String& linked_uid = linked_pair.first.get();
|
||||||
|
String& linked_relation = linked_pair.second.get();
|
||||||
|
if (linked_uid == wxEmptyString) continue;
|
||||||
|
// If it's an added card, replace the link
|
||||||
|
if (all_added_uids.find(linked_uid) != all_added_uids.end()) {
|
||||||
|
all_added_uids.at(linked_uid)->updateLink(old_uid, new_uid);
|
||||||
|
}
|
||||||
|
// Otherwise, if it's an existing card, copy the link
|
||||||
|
else if (all_existing_uids.find(linked_uid) != all_existing_uids.end()) {
|
||||||
|
all_existing_uids.at(linked_uid)->copyLink(set, old_uid, new_uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add or remove cards
|
||||||
action.perform(set.cards, to_undo);
|
action.perform(set.cards, to_undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Reorder cards
|
// ----------------------------------------------------------------------------- : Reorder cards
|
||||||
|
|
||||||
ReorderCardsAction::ReorderCardsAction(Set& set, size_t card_id1, size_t card_id2)
|
ReorderCardsAction::ReorderCardsAction(Set& set, size_t card_id1, size_t card_id2)
|
||||||
@@ -55,13 +99,50 @@ void ReorderCardsAction::perform(bool to_undo) {
|
|||||||
assert(card_id1 < set.cards.size());
|
assert(card_id1 < set.cards.size());
|
||||||
assert(card_id2 < set.cards.size());
|
assert(card_id2 < set.cards.size());
|
||||||
#endif
|
#endif
|
||||||
if (card_id1 >= set.cards.size() || card_id2 < set.cards.size()) {
|
if (card_id1 >= set.cards.size() || card_id2 >= set.cards.size()) {
|
||||||
// TODO : Too lazy to fix this right now.
|
// TODO : Too lazy to fix this right now.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
swap(set.cards[card_id1], set.cards[card_id2]);
|
swap(set.cards[card_id1], set.cards[card_id2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Link cards
|
||||||
|
|
||||||
|
LinkCardsAction::LinkCardsAction(Set& set, const CardP& selected_card, vector<CardP>& linked_cards, const String& selected_relation, const String& linked_relation)
|
||||||
|
: CardListAction(set), selected_card(selected_card), linked_cards(linked_cards), selected_relation(selected_relation), linked_relation(linked_relation)
|
||||||
|
{}
|
||||||
|
|
||||||
|
String LinkCardsAction::getName(bool to_undo) const {
|
||||||
|
return _("Link cards");
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkCardsAction::perform(bool to_undo) {
|
||||||
|
if (!to_undo) {
|
||||||
|
selected_card->link(set, linked_cards, selected_relation, linked_relation);
|
||||||
|
} else {
|
||||||
|
selected_card->unlink(linked_cards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlinkCardsAction::UnlinkCardsAction(Set& set, const CardP& selected_card, CardP& unlinked_card)
|
||||||
|
: CardListAction(set), selected_card(selected_card), unlinked_card(unlinked_card)
|
||||||
|
{}
|
||||||
|
|
||||||
|
String UnlinkCardsAction::getName(bool to_undo) const {
|
||||||
|
return _("Unlink card");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnlinkCardsAction::perform(bool to_undo) {
|
||||||
|
if (!to_undo) {
|
||||||
|
pair<String, String> relations = selected_card->unlink(unlinked_card);
|
||||||
|
selected_relation = relations.first;
|
||||||
|
unlinked_relation = relations.second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selected_card->link(set, unlinked_card, selected_relation, unlinked_relation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Change stylesheet
|
// ----------------------------------------------------------------------------- : Change stylesheet
|
||||||
|
|
||||||
String DisplayChangeAction::getName(bool to_undo) const {
|
String DisplayChangeAction::getName(bool to_undo) const {
|
||||||
|
|||||||
@@ -64,6 +64,37 @@ public:
|
|||||||
const size_t card_id1, card_id2; ///< Positions of the two cards to swap
|
const size_t card_id1, card_id2; ///< Positions of the two cards to swap
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Link cards
|
||||||
|
|
||||||
|
/// Add a link between two or more cards
|
||||||
|
class LinkCardsAction : public CardListAction {
|
||||||
|
public:
|
||||||
|
LinkCardsAction(Set& set, const CardP& selected_card, vector<CardP>& linked_cards, const String& selected_relation, const String& linked_relation);
|
||||||
|
|
||||||
|
String getName(bool to_undo) const override;
|
||||||
|
void perform(bool to_undo) override;
|
||||||
|
|
||||||
|
//private:
|
||||||
|
CardP selected_card; ///< The card currently selected in the cards tab
|
||||||
|
vector<CardP> linked_cards; ///< The cards that will be linked to the selected card
|
||||||
|
String selected_relation; ///< The nature of the relation of the selected card
|
||||||
|
String linked_relation; ///< The nature of the relation of the linked cards
|
||||||
|
};
|
||||||
|
/// Remove a link between two cards
|
||||||
|
class UnlinkCardsAction : public CardListAction {
|
||||||
|
public:
|
||||||
|
UnlinkCardsAction(Set& set, const CardP& selected_card, CardP& unlinked_card);
|
||||||
|
|
||||||
|
String getName(bool to_undo) const override;
|
||||||
|
void perform(bool to_undo) override;
|
||||||
|
|
||||||
|
//private:
|
||||||
|
CardP selected_card; ///< The card currently selected in the cards tab
|
||||||
|
CardP unlinked_card; ///< The card that will be unlinked from the selected card
|
||||||
|
String selected_relation; ///< The nature of the relation of the selected card
|
||||||
|
String unlinked_relation; ///< The nature of the relation of the unlinked card
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Change stylesheet
|
// ----------------------------------------------------------------------------- : Change stylesheet
|
||||||
|
|
||||||
/// An action that affects the rendering/display/look of a set or cards in the set
|
/// An action that affects the rendering/display/look of a set or cards in the set
|
||||||
|
|||||||
+231
-1
@@ -8,19 +8,23 @@
|
|||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
|
#include <data/set.hpp>
|
||||||
#include <data/game.hpp>
|
#include <data/game.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/field.hpp>
|
#include <data/field.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
#include <util/reflect.hpp>
|
#include <util/reflect.hpp>
|
||||||
#include <util/delayed_index_maps.hpp>
|
#include <util/delayed_index_maps.hpp>
|
||||||
|
#include <util/uid.hpp>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Card
|
// ----------------------------------------------------------------------------- : Card
|
||||||
|
|
||||||
Card::Card()
|
Card::Card()
|
||||||
// for files made before we saved these times, set the time to 'yesterday'
|
// for files made before we saved these, set the time to 'yesterday', generate a uid
|
||||||
: time_created (wxDateTime::Now().Subtract(wxDateSpan::Day()).ResetTime())
|
: time_created (wxDateTime::Now().Subtract(wxDateSpan::Day()).ResetTime())
|
||||||
, time_modified(wxDateTime::Now().Subtract(wxDateSpan::Day()).ResetTime())
|
, time_modified(wxDateTime::Now().Subtract(wxDateSpan::Day()).ResetTime())
|
||||||
|
, uid(generate_uid())
|
||||||
, has_styling(false)
|
, has_styling(false)
|
||||||
{
|
{
|
||||||
if (!game_for_reading()) {
|
if (!game_for_reading()) {
|
||||||
@@ -32,6 +36,7 @@ Card::Card()
|
|||||||
Card::Card(const Game& game)
|
Card::Card(const Game& game)
|
||||||
: time_created (wxDateTime::Now())
|
: time_created (wxDateTime::Now())
|
||||||
, time_modified(wxDateTime::Now())
|
, time_modified(wxDateTime::Now())
|
||||||
|
, uid(generate_uid())
|
||||||
, has_styling(false)
|
, has_styling(false)
|
||||||
{
|
{
|
||||||
data.init(game.card_fields);
|
data.init(game.card_fields);
|
||||||
@@ -60,6 +65,222 @@ bool Card::contains(QuickFilterPart const& query) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Card::link(const Set& set, const vector<CardP>& linked_cards, const String& selected_relation, const String& linked_relation)
|
||||||
|
{
|
||||||
|
unlink(linked_cards);
|
||||||
|
|
||||||
|
unordered_set<String> all_existing_uids;
|
||||||
|
FOR_EACH(card, set.cards) {
|
||||||
|
all_existing_uids.insert(card->uid);
|
||||||
|
}
|
||||||
|
int free_link_count = 0;
|
||||||
|
THIS_LINKED_PAIRS(this_linked_pairs);
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
if (
|
||||||
|
this_linked_uid == wxEmptyString || // Not a reference
|
||||||
|
all_existing_uids.find(this_linked_uid) == all_existing_uids.end() // Reference to nonexistent card
|
||||||
|
) free_link_count++;
|
||||||
|
}
|
||||||
|
if (free_link_count < linked_cards.size()) {
|
||||||
|
queue_message(MESSAGE_WARNING, _ERROR_("not enough free links"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<CardP> all_missed_cards;
|
||||||
|
FOR_EACH(linked_card, linked_cards) {
|
||||||
|
bool written = false;
|
||||||
|
// Try to write to a free spot
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
String& this_linked_relation = this_linked_pair.second.get();
|
||||||
|
if (this_linked_uid == wxEmptyString) {
|
||||||
|
this_linked_uid = linked_card->uid;
|
||||||
|
this_linked_relation = linked_relation;
|
||||||
|
written = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Try to write to an erasable spot
|
||||||
|
if (!written) {
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
String& this_linked_relation = this_linked_pair.second.get();
|
||||||
|
if (all_existing_uids.find(this_linked_uid) == all_existing_uids.end()) {
|
||||||
|
this_linked_uid = linked_card->uid;
|
||||||
|
this_linked_relation = linked_relation;
|
||||||
|
written = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!written) {
|
||||||
|
// Should be impossible to end up here?
|
||||||
|
}
|
||||||
|
|
||||||
|
OTHER_LINKED_PAIRS(linked_pairs, linked_card);
|
||||||
|
written = false;
|
||||||
|
// Try to write to a free spot
|
||||||
|
FOR_EACH(linked_pair, linked_pairs) {
|
||||||
|
String& linked_uid = linked_pair.first.get();
|
||||||
|
String& linked_relation = linked_pair.second.get();
|
||||||
|
if (linked_uid == wxEmptyString) {
|
||||||
|
linked_uid = uid;
|
||||||
|
linked_relation = selected_relation;
|
||||||
|
written = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Try to write to an erasable spot
|
||||||
|
if (!written) {
|
||||||
|
FOR_EACH(linked_pair, linked_pairs) {
|
||||||
|
String& linked_uid = linked_pair.first.get();
|
||||||
|
String& linked_relation = linked_pair.second.get();
|
||||||
|
if (all_existing_uids.find(linked_uid) == all_existing_uids.end()) {
|
||||||
|
linked_uid = uid;
|
||||||
|
linked_relation = selected_relation;
|
||||||
|
written = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Notify we couldn't write
|
||||||
|
if (!written) {
|
||||||
|
all_missed_cards.push_back(linked_card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (all_missed_cards.size() > 0) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << _ERROR_("could not link");
|
||||||
|
for (size_t pos = 0; pos < all_missed_cards.size(); ++pos) {
|
||||||
|
ss << all_missed_cards[pos]->identification();
|
||||||
|
if (pos < all_missed_cards.size() - 1) ss << ", ";
|
||||||
|
};
|
||||||
|
String wxString(ss.str().c_str(), wxConvUTF8);
|
||||||
|
queue_message(MESSAGE_WARNING, wxString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Card::link(const Set& set, CardP& linked_card, const String& selected_relation, const String& linked_relation)
|
||||||
|
{
|
||||||
|
vector<CardP> linked_cards { linked_card };
|
||||||
|
link(set, linked_cards, selected_relation, linked_relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Card::unlink(const vector<CardP>& unlinked_cards)
|
||||||
|
{
|
||||||
|
for (size_t pos = 0; pos < unlinked_cards.size(); ++pos) {
|
||||||
|
CardP unlinked_card = unlinked_cards[pos];
|
||||||
|
unlink(unlinked_card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<String, String> Card::unlink(CardP& unlinked_card)
|
||||||
|
{
|
||||||
|
String old_selected_relation = wxEmptyString;
|
||||||
|
THIS_LINKED_PAIRS(this_linked_pairs);
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
String& this_linked_relation = this_linked_pair.second.get();
|
||||||
|
if (this_linked_uid == unlinked_card->uid) {
|
||||||
|
old_selected_relation = this_linked_relation;
|
||||||
|
this_linked_uid = wxEmptyString;
|
||||||
|
this_linked_relation = wxEmptyString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String old_unlinked_relation = wxEmptyString;
|
||||||
|
OTHER_LINKED_PAIRS(unlinked_pairs, unlinked_card);
|
||||||
|
FOR_EACH(unlinked_pair, unlinked_pairs) {
|
||||||
|
String& unlinked_uid = unlinked_pair.first.get();
|
||||||
|
String& unlinked_relation = unlinked_pair.second.get();
|
||||||
|
if (unlinked_uid == uid) {
|
||||||
|
old_unlinked_relation = unlinked_relation;
|
||||||
|
unlinked_uid = wxEmptyString;
|
||||||
|
unlinked_relation = wxEmptyString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return make_pair(old_selected_relation, old_unlinked_relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Card::copyLink(const Set& set, String old_uid, String new_uid) {
|
||||||
|
// Find what relation we need to copy
|
||||||
|
String relation_copy = wxEmptyString;
|
||||||
|
THIS_LINKED_PAIRS(this_linked_pairs);
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
String& this_linked_relation = this_linked_pair.second.get();
|
||||||
|
if (this_linked_uid == old_uid) {
|
||||||
|
relation_copy = this_linked_relation;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Nothing to copy
|
||||||
|
if (relation_copy == wxEmptyString) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to copy to a free spot
|
||||||
|
bool written = false;
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
String& this_linked_relation = this_linked_pair.second.get();
|
||||||
|
if (this_linked_uid == wxEmptyString) {
|
||||||
|
this_linked_uid = new_uid;
|
||||||
|
this_linked_relation = relation_copy;
|
||||||
|
written = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Try to copy to an erasable spot
|
||||||
|
if (!written) {
|
||||||
|
unordered_set<String> all_existing_uids;
|
||||||
|
FOR_EACH(card, set.cards) {
|
||||||
|
all_existing_uids.insert(card->uid);
|
||||||
|
}
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
String& this_linked_relation = this_linked_pair.second.get();
|
||||||
|
if (all_existing_uids.find(this_linked_uid) == all_existing_uids.end()) {
|
||||||
|
this_linked_uid = new_uid;
|
||||||
|
this_linked_relation = relation_copy;
|
||||||
|
written = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Notify we couldn't copy
|
||||||
|
if (!written) {
|
||||||
|
queue_message(MESSAGE_WARNING, _ERROR_("not enough free links for copy"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Card::updateLink(String old_uid, String new_uid) {
|
||||||
|
THIS_LINKED_PAIRS(this_linked_pairs);
|
||||||
|
FOR_EACH(this_linked_pair, this_linked_pairs) {
|
||||||
|
String& this_linked_uid = this_linked_pair.first.get();
|
||||||
|
if (this_linked_uid == old_uid) {
|
||||||
|
this_linked_uid = new_uid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<pair<CardP, String>> Card::getLinkedCards(const Set& set) {
|
||||||
|
unordered_map<String, String> links{
|
||||||
|
{ linked_card_1, linked_relation_1 },
|
||||||
|
{ linked_card_2, linked_relation_2 },
|
||||||
|
{ linked_card_3, linked_relation_3 },
|
||||||
|
{ linked_card_4, linked_relation_4 }
|
||||||
|
};
|
||||||
|
vector<pair<CardP, String>> linked_cards;
|
||||||
|
FOR_EACH(other_card, set.cards) {
|
||||||
|
if (links.find(other_card->uid) != links.end()) {
|
||||||
|
linked_cards.push_back(make_pair(other_card, links.at(other_card->uid)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return linked_cards;
|
||||||
|
}
|
||||||
|
|
||||||
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
|
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
|
||||||
return extra_data.get(stylesheet.name(), stylesheet.extra_card_fields);
|
return extra_data.get(stylesheet.name(), stylesheet.extra_card_fields);
|
||||||
}
|
}
|
||||||
@@ -89,6 +310,15 @@ IMPLEMENT_REFLECTION(Card) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
REFLECT(notes);
|
REFLECT(notes);
|
||||||
|
REFLECT(uid);
|
||||||
|
REFLECT(linked_card_1);
|
||||||
|
REFLECT(linked_card_2);
|
||||||
|
REFLECT(linked_card_3);
|
||||||
|
REFLECT(linked_card_4);
|
||||||
|
REFLECT(linked_relation_1);
|
||||||
|
REFLECT(linked_relation_2);
|
||||||
|
REFLECT(linked_relation_3);
|
||||||
|
REFLECT(linked_relation_4);
|
||||||
REFLECT(time_created);
|
REFLECT(time_created);
|
||||||
REFLECT(time_modified);
|
REFLECT(time_modified);
|
||||||
REFLECT(extra_data); // don't allow scripts to depend on style specific data
|
REFLECT(extra_data); // don't allow scripts to depend on style specific data
|
||||||
|
|||||||
@@ -17,11 +17,15 @@
|
|||||||
class Game;
|
class Game;
|
||||||
class Dependency;
|
class Dependency;
|
||||||
class Keyword;
|
class Keyword;
|
||||||
|
DECLARE_POINTER_TYPE(Set);
|
||||||
DECLARE_POINTER_TYPE(Card);
|
DECLARE_POINTER_TYPE(Card);
|
||||||
DECLARE_POINTER_TYPE(Field);
|
DECLARE_POINTER_TYPE(Field);
|
||||||
DECLARE_POINTER_TYPE(Value);
|
DECLARE_POINTER_TYPE(Value);
|
||||||
DECLARE_POINTER_TYPE(StyleSheet);
|
DECLARE_POINTER_TYPE(StyleSheet);
|
||||||
|
|
||||||
|
#define THIS_LINKED_PAIRS(var) vector<pair<reference_wrapper<String>, reference_wrapper<String>>> var { make_pair(ref(linked_card_1), ref(linked_relation_1)), make_pair(ref(linked_card_2), ref(linked_relation_2)), make_pair(ref(linked_card_3), ref(linked_relation_3)), make_pair(ref(linked_card_4), ref(linked_relation_4)) }
|
||||||
|
#define OTHER_LINKED_PAIRS(var, other_card) vector<pair<reference_wrapper<String>, reference_wrapper<String>>> var { make_pair(ref(other_card->linked_card_1), ref(other_card->linked_relation_1)), make_pair(ref(other_card->linked_card_2), ref(other_card->linked_relation_2)), make_pair(ref(other_card->linked_card_3), ref(other_card->linked_relation_3)), make_pair(ref(other_card->linked_card_4), ref(other_card->linked_relation_4)) }
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Card
|
// ----------------------------------------------------------------------------- : Card
|
||||||
|
|
||||||
/// A card from a card Set
|
/// A card from a card Set
|
||||||
@@ -37,6 +41,18 @@ public:
|
|||||||
IndexMap<FieldP, ValueP> data;
|
IndexMap<FieldP, ValueP> data;
|
||||||
/// Notes for this card
|
/// Notes for this card
|
||||||
String notes;
|
String notes;
|
||||||
|
/// Unique identifier for this card, so other cards can refer to it, and be linked to it
|
||||||
|
String uid;
|
||||||
|
/// Up to four uid of other cards, to encode relations such as front face/back face, or generator/token, etc...
|
||||||
|
String linked_card_1;
|
||||||
|
String linked_card_2;
|
||||||
|
String linked_card_3;
|
||||||
|
String linked_card_4;
|
||||||
|
/// Nature of the relatation with the respective linked card, such as back face, or token, etc...
|
||||||
|
String linked_relation_1;
|
||||||
|
String linked_relation_2;
|
||||||
|
String linked_relation_3;
|
||||||
|
String linked_relation_4;
|
||||||
/// Time the card was created/last modified
|
/// Time the card was created/last modified
|
||||||
wxDateTime time_created, time_modified;
|
wxDateTime time_created, time_modified;
|
||||||
/// Alternative style to use for this card
|
/// Alternative style to use for this card
|
||||||
@@ -64,6 +80,17 @@ public:
|
|||||||
/// Does any field contains the given query string?
|
/// Does any field contains the given query string?
|
||||||
bool contains(QuickFilterPart const& query) const;
|
bool contains(QuickFilterPart const& query) const;
|
||||||
|
|
||||||
|
/// Link or unlink other cards to this card
|
||||||
|
void link(const Set& set, const vector<CardP>& linked_cards, const String& selected_relation, const String& linked_relation);
|
||||||
|
void link(const Set& set, CardP& linked_card, const String& selected_relation, const String& linked_relation);
|
||||||
|
void unlink(const vector<CardP>& linked_cards);
|
||||||
|
pair<String, String> unlink(CardP& unlinked_card); // Returns the relations that were deleted, so we can undo
|
||||||
|
|
||||||
|
void copyLink(const Set& set, String old_uid, String new_uid);
|
||||||
|
void updateLink(String old_uid, String new_uid);
|
||||||
|
|
||||||
|
vector<pair<CardP, String>> getLinkedCards(const Set& set);
|
||||||
|
|
||||||
/// Find a value in the data by name and type
|
/// Find a value in the data by name and type
|
||||||
template <typename T> T& value(const String& name) {
|
template <typename T> T& value(const String& name) {
|
||||||
for(IndexMap<FieldP, ValueP>::iterator it = data.begin() ; it != data.end() ; ++it) {
|
for(IndexMap<FieldP, ValueP>::iterator it = data.begin() ; it != data.end() ; ++it) {
|
||||||
|
|||||||
+36
-6
@@ -68,14 +68,14 @@ IMPLEMENT_REFLECTION(Field) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Field::after_reading(Version ver) {
|
void Field::after_reading(Version ver) {
|
||||||
name = canonical_name_form(name);
|
name = canonical_name_form(name);
|
||||||
if(caption.default_.empty()) caption.default_ = tr(package_relative_filename, name, name_to_caption);
|
if(caption.default_.empty()) caption.default_ = tr(package_relative_filename, name, name_to_caption);
|
||||||
if(card_list_name.default_.empty()) card_list_name.default_ = tr(package_relative_filename, caption.default_, capitalize);
|
if(card_list_name.default_.empty()) card_list_name.default_ = tr(package_relative_filename, caption.default_, capitalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
intrusive_ptr<Field> read_new<Field>(Reader& reader) {
|
intrusive_ptr<Field> read_new<Field>(Reader& reader) {
|
||||||
intrusive_ptr<Field> field;
|
intrusive_ptr<Field> field;
|
||||||
// there must be a type specified
|
// there must be a type specified
|
||||||
String type;
|
String type;
|
||||||
reader.handle(_("type"), type);
|
reader.handle(_("type"), type);
|
||||||
@@ -95,7 +95,7 @@ intrusive_ptr<Field> read_new<Field>(Reader& reader) {
|
|||||||
} else {
|
} else {
|
||||||
reader.warning(_ERROR_1_("unsupported field type", type));
|
reader.warning(_ERROR_1_("unsupported field type", type));
|
||||||
throw ParseError(_ERROR_("aborting parsing"));
|
throw ParseError(_ERROR_("aborting parsing"));
|
||||||
}
|
}
|
||||||
field->package_relative_filename = reader.getPackage()->relativeFilename().Clone();
|
field->package_relative_filename = reader.getPackage()->relativeFilename().Clone();
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
@@ -222,8 +222,38 @@ void Style::checkContentDependencies(Context& ctx, const Dependency& dep) const
|
|||||||
|
|
||||||
void Style::markDependencyMember(const String& name, const Dependency& dep) const {
|
void Style::markDependencyMember(const String& name, const Dependency& dep) const {
|
||||||
// mark dependencies on content
|
// mark dependencies on content
|
||||||
if (dep.type == DEP_DUMMY && dep.index == false && (starts_with(name, _("content")) || name == "layout") ) {
|
if (
|
||||||
// anything that starts with "content_" is a content property
|
dep.type == DEP_DUMMY && dep.index == false && (
|
||||||
|
starts_with(name, _("content")) ||
|
||||||
|
name == "layout" ||
|
||||||
|
name == "lines" ||
|
||||||
|
name == "paragraphs" ||
|
||||||
|
name == "blocks" ||
|
||||||
|
name == "separators" ||
|
||||||
|
name == "font" ||
|
||||||
|
name == "symbol_font" ||
|
||||||
|
name == "always_symbol" ||
|
||||||
|
name == "allow_formating" ||
|
||||||
|
name == "alignment" ||
|
||||||
|
name == "padding_left" ||
|
||||||
|
name == "padding_right" ||
|
||||||
|
name == "padding_top" ||
|
||||||
|
name == "padding_bottom" ||
|
||||||
|
name == "padding_left_min" ||
|
||||||
|
name == "padding_right_min" ||
|
||||||
|
name == "padding_top_min" ||
|
||||||
|
name == "padding_bottom_min" ||
|
||||||
|
name == "line_height_soft" ||
|
||||||
|
name == "line_height_hard" ||
|
||||||
|
name == "line_height_line" ||
|
||||||
|
name == "line_height_soft_max" ||
|
||||||
|
name == "line_height_hard_max" ||
|
||||||
|
name == "line_height_line_max" ||
|
||||||
|
name == "paragraph_height" ||
|
||||||
|
name == "block_height_min" ||
|
||||||
|
name == "direction"
|
||||||
|
)
|
||||||
|
) {
|
||||||
const_cast<Dependency&>(dep).index = true;
|
const_cast<Dependency&>(dep).index = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ public:
|
|||||||
Alignment card_list_align; ///< Alignment of the card list colummn.
|
Alignment card_list_align; ///< Alignment of the card list colummn.
|
||||||
OptionalScript sort_script; ///< The script to use when sorting this, if not the value.
|
OptionalScript sort_script; ///< The script to use when sorting this, if not the value.
|
||||||
OptionalScript import_script; ///< The script to apply to the supplied value, when creating a new card.
|
OptionalScript import_script; ///< The script to apply to the supplied value, when creating a new card.
|
||||||
Dependencies dependent_scripts; ///< Scripts that depend on values of this field
|
Dependencies dependent_scripts; ///< Scripts that depend on values of this field
|
||||||
String package_relative_filename;
|
String package_relative_filename;
|
||||||
|
|
||||||
/// Creates a new Value corresponding to this Field
|
/// Creates a new Value corresponding to this Field
|
||||||
|
|||||||
+50
-50
@@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <data/font.hpp>
|
#include <data/font.hpp>
|
||||||
#include <wx/stdpaths.h>
|
#include <wx/stdpaths.h>
|
||||||
#include <wx/dir.h>
|
#include <wx/dir.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Font
|
// ----------------------------------------------------------------------------- : Font
|
||||||
|
|
||||||
Font::Font()
|
Font::Font()
|
||||||
@@ -27,59 +27,59 @@ Font::Font()
|
|||||||
, separator_color(Color(0,0,0,128))
|
, separator_color(Color(0,0,0,128))
|
||||||
, flags(FONT_NORMAL)
|
, flags(FONT_NORMAL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool Font::PreloadResourceFonts(bool recursive) {
|
|
||||||
#if wxUSE_PRIVATE_FONTS
|
|
||||||
String pathSeparator(wxFileName::GetPathSeparator());
|
|
||||||
String appPath(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
|
|
||||||
wxDir appDir(appPath);
|
|
||||||
if (!appDir.IsOpened()) return true;
|
|
||||||
|
|
||||||
bool preloadHadErrors = false;
|
bool Font::PreloadResourceFonts(bool recursive) {
|
||||||
|
#if wxUSE_PRIVATE_FONTS
|
||||||
|
String pathSeparator(wxFileName::GetPathSeparator());
|
||||||
|
String appPath(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
|
||||||
|
wxDir appDir(appPath);
|
||||||
|
if (!appDir.IsOpened()) return true;
|
||||||
|
|
||||||
|
bool preloadHadErrors = false;
|
||||||
wxString folder;
|
wxString folder;
|
||||||
bool cont = appDir.GetFirst(&folder, wxEmptyString, wxDIR_DIRS);
|
bool cont = appDir.GetFirst(&folder, wxEmptyString, wxDIR_DIRS);
|
||||||
while (cont)
|
while (cont)
|
||||||
{
|
{
|
||||||
if (folder.Lower().Contains("fonts")) {
|
if (folder.Lower().Contains("fonts")) {
|
||||||
String folderPath = appPath + pathSeparator + folder + pathSeparator;
|
String folderPath = appPath + pathSeparator + folder + pathSeparator;
|
||||||
|
|
||||||
// tally fonts
|
// tally fonts
|
||||||
vector<String> fontFilePaths;
|
vector<String> fontFilePaths;
|
||||||
TallyResourceFonts(folderPath, fontFilePaths, recursive);
|
TallyResourceFonts(folderPath, fontFilePaths, recursive);
|
||||||
|
|
||||||
// load fonts
|
// load fonts
|
||||||
for (const String& fontFilePath : fontFilePaths) {
|
for (const String& fontFilePath : fontFilePaths) {
|
||||||
if (!wxFont::AddPrivateFont(fontFilePath)) {
|
if (!wxFont::AddPrivateFont(fontFilePath)) {
|
||||||
preloadHadErrors = true;
|
preloadHadErrors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cont = appDir.GetNext(&folder);
|
cont = appDir.GetNext(&folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return preloadHadErrors;
|
return preloadHadErrors;
|
||||||
|
|
||||||
#endif // wxUSE_PRIVATE_FONTS
|
#endif // wxUSE_PRIVATE_FONTS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::TallyResourceFonts(String fontsDirectoryPath, vector<String>& fontFilePaths, bool recursive) {
|
void Font::TallyResourceFonts(String fontsDirectoryPath, vector<String>& fontFilePaths, bool recursive) {
|
||||||
wxDir fontsDirectory(fontsDirectoryPath);
|
wxDir fontsDirectory(fontsDirectoryPath);
|
||||||
String fontFileName = wxEmptyString;
|
String fontFileName = wxEmptyString;
|
||||||
bool hasNext = fontsDirectory.GetFirst(&fontFileName);
|
bool hasNext = fontsDirectory.GetFirst(&fontFileName);
|
||||||
while (hasNext) {
|
while (hasNext) {
|
||||||
String fontFilePath = fontsDirectoryPath + fontFileName;
|
String fontFilePath = fontsDirectoryPath + fontFileName;
|
||||||
if (wxDirExists(fontFilePath)) {
|
if (wxDirExists(fontFilePath)) {
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
TallyResourceFonts(fontFilePath + wxFileName::GetPathSeparator(), fontFilePaths, true);
|
TallyResourceFonts(fontFilePath + wxFileName::GetPathSeparator(), fontFilePaths, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (fontFilePath.EndsWith(_(".ttf")) || fontFilePath.EndsWith(_(".otf"))) {
|
else if (fontFilePath.EndsWith(_(".ttf")) || fontFilePath.EndsWith(_(".otf"))) {
|
||||||
fontFilePaths.push_back(fontFilePath);
|
fontFilePaths.push_back(fontFilePath);
|
||||||
}
|
}
|
||||||
hasNext = fontsDirectory.GetNext(&fontFileName);
|
hasNext = fontsDirectory.GetNext(&fontFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Font::update(Context& ctx) {
|
bool Font::update(Context& ctx) {
|
||||||
bool changes = false;
|
bool changes = false;
|
||||||
|
|||||||
+10
-9
@@ -46,15 +46,16 @@ public:
|
|||||||
Scriptable<double> shadow_displacement_y;///< Position of the shadow
|
Scriptable<double> shadow_displacement_y;///< Position of the shadow
|
||||||
Scriptable<double> shadow_blur; ///< Blur radius of the shadow
|
Scriptable<double> shadow_blur; ///< Blur radius of the shadow
|
||||||
Color separator_color; ///< Color for <sep> text
|
Color separator_color; ///< Color for <sep> text
|
||||||
int flags; ///< FontFlags for this font
|
int flags; ///< FontFlags for this font
|
||||||
|
|
||||||
Font();
|
Font();
|
||||||
|
|
||||||
/// Load fonts (.ttf or .otf) from all directories in the app directory that contain "fonts" in their names,
|
/// Load fonts (.ttf or .otf) from all directories in the app directory that contain "fonts" in their names,
|
||||||
/// and optionaly their subdirectories, returns true if there were errors
|
/// and optionaly their subdirectories, returns true if there were errors
|
||||||
static bool PreloadResourceFonts(bool recursive);
|
static bool PreloadResourceFonts(bool recursive);
|
||||||
/// Adds font file paths from the given directory into fontFilePaths
|
/// Adds font file paths from the given directory into fontFilePaths
|
||||||
static void TallyResourceFonts(String fontsDirectoryPath, vector<String>& fontFilePaths, bool recursive);
|
static void TallyResourceFonts(String fontsDirectoryPath, vector<String>& fontFilePaths, bool recursive);
|
||||||
|
|
||||||
/// Update the scritables, returns true if there is a change
|
/// Update the scritables, returns true if there is a change
|
||||||
bool update(Context& ctx);
|
bool update(Context& ctx);
|
||||||
/// Add the given dependency to the dependent_scripts list for the variables this font depends on
|
/// Add the given dependency to the dependent_scripts list for the variables this font depends on
|
||||||
@@ -70,7 +71,7 @@ public:
|
|||||||
|
|
||||||
/// Convert this font to a wxFont
|
/// Convert this font to a wxFont
|
||||||
wxFont toWxFont(double scale) const;
|
wxFont toWxFont(double scale) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_REFLECTION();
|
DECLARE_REFLECTION();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -147,6 +147,9 @@ CardsOnClipboard::CardsOnClipboard(const SetP& set, const vector<CardP>& cards)
|
|||||||
if (cards.size() == 1) {
|
if (cards.size() == 1) {
|
||||||
Add(new wxBitmapDataObject(export_bitmap(set, cards[0])));
|
Add(new wxBitmapDataObject(export_bitmap(set, cards[0])));
|
||||||
}
|
}
|
||||||
|
else if (cards.size() < 6) {
|
||||||
|
Add(new wxBitmapDataObject(export_bitmap(set, cards, true, 0, 1.0, 0.0)));
|
||||||
|
}
|
||||||
// Conversion to serialized card format
|
// Conversion to serialized card format
|
||||||
Add(new CardsDataObject(set, cards), true);
|
Add(new CardsDataObject(set, cards), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,11 +99,12 @@ void export_images(const SetP& set, const vector<CardP>& cards,
|
|||||||
void export_image(const SetP& set, const CardP& card, const String& filename);
|
void export_image(const SetP& set, const CardP& card, const String& filename);
|
||||||
|
|
||||||
/// Generate a bitmap image of a card
|
/// Generate a bitmap image of a card
|
||||||
Bitmap export_bitmap(const SetP& set, const CardP& card);
|
Bitmap export_bitmap(const SetP& set, const CardP& card);
|
||||||
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, const Radians angle_radians);
|
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, const Radians angle_radians);
|
||||||
|
Bitmap export_bitmap(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians);
|
||||||
|
|
||||||
/// Export a set to Magic Workstation format
|
/// Export a set to Magic Workstation format
|
||||||
void export_mws(Window* parent, const SetP& set);
|
void export_mws(Window* parent, const SetP& set);
|
||||||
|
|
||||||
/// Export a set to Apprentice
|
/// Export a set to Apprentice
|
||||||
void export_apprentice(Window* parent, const SetP& set);
|
void export_apprentice(Window* parent, const SetP& set);
|
||||||
|
|||||||
+87
-35
@@ -13,6 +13,7 @@
|
|||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/settings.hpp>
|
#include <data/settings.hpp>
|
||||||
|
#include <gui/util.hpp>
|
||||||
#include <render/card/viewer.hpp>
|
#include <render/card/viewer.hpp>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
|
|
||||||
@@ -25,47 +26,47 @@ void export_image(const SetP& set, const CardP& card, const String& filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UnzoomedDataViewer : public DataViewer {
|
class UnzoomedDataViewer : public DataViewer {
|
||||||
public:
|
public:
|
||||||
UnzoomedDataViewer();
|
UnzoomedDataViewer();
|
||||||
UnzoomedDataViewer(double zoom, double angle);
|
UnzoomedDataViewer(double zoom, double angle);
|
||||||
virtual ~UnzoomedDataViewer() {};
|
virtual ~UnzoomedDataViewer() {};
|
||||||
Rotation getRotation() const override;
|
Rotation getRotation() const override;
|
||||||
private:
|
private:
|
||||||
double zoom;
|
double zoom;
|
||||||
double angle;
|
double angle;
|
||||||
bool declared_values;
|
bool declared_values;
|
||||||
};
|
};
|
||||||
|
|
||||||
UnzoomedDataViewer::UnzoomedDataViewer()
|
UnzoomedDataViewer::UnzoomedDataViewer()
|
||||||
: zoom(1.0)
|
: zoom(1.0)
|
||||||
, angle(0.0)
|
, angle(0.0)
|
||||||
, declared_values(false)
|
, declared_values(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
UnzoomedDataViewer::UnzoomedDataViewer(const double zoom, const Radians angle = 0.0)
|
UnzoomedDataViewer::UnzoomedDataViewer(const double zoom, const Radians angle = 0.0)
|
||||||
: zoom(zoom)
|
: zoom(zoom)
|
||||||
, angle(angle)
|
, angle(angle)
|
||||||
, declared_values(true)
|
, declared_values(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Rotation UnzoomedDataViewer::getRotation() const {
|
Rotation UnzoomedDataViewer::getRotation() const {
|
||||||
if (!stylesheet) stylesheet = set->stylesheet;
|
if (!stylesheet) stylesheet = set->stylesheet;
|
||||||
if (declared_values) {
|
if (declared_values) {
|
||||||
return Rotation(angle, stylesheet->getCardRect(), zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
return Rotation(angle, stylesheet->getCardRect(), zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
double export_zoom = settings.stylesheetSettingsFor(set->stylesheetFor(card)).export_zoom();
|
double export_zoom = settings.stylesheetSettingsFor(set->stylesheetFor(card)).export_zoom();
|
||||||
bool use_viewer_rotation = !settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export();
|
bool use_viewer_rotation = !settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export();
|
||||||
|
|
||||||
if (use_viewer_rotation) {
|
if (use_viewer_rotation) {
|
||||||
return Rotation(DataViewer::getRotation().getAngle(), stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
return Rotation(DataViewer::getRotation().getAngle(), stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||||
} else {
|
} else {
|
||||||
return Rotation(angle, stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
return Rotation(angle, stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap export_bitmap(const SetP& set, const CardP& card) {
|
Bitmap export_bitmap(const SetP& set, const CardP& card) {
|
||||||
if (!set) throw Error(_("no set"));
|
if (!set) throw Error(_("no set"));
|
||||||
UnzoomedDataViewer viewer = UnzoomedDataViewer();
|
UnzoomedDataViewer viewer = UnzoomedDataViewer();
|
||||||
viewer.setSet(set);
|
viewer.setSet(set);
|
||||||
viewer.setCard(card);
|
viewer.setCard(card);
|
||||||
@@ -79,11 +80,11 @@ Bitmap export_bitmap(const SetP& set, const CardP& card) {
|
|||||||
// draw
|
// draw
|
||||||
viewer.draw(dc);
|
viewer.draw(dc);
|
||||||
dc.SelectObject(wxNullBitmap);
|
dc.SelectObject(wxNullBitmap);
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, const Radians angle = 0.0) {
|
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, const Radians angle = 0.0) {
|
||||||
if (!set) throw Error(_("no set"));
|
if (!set) throw Error(_("no set"));
|
||||||
UnzoomedDataViewer viewer = UnzoomedDataViewer(zoom, angle);
|
UnzoomedDataViewer viewer = UnzoomedDataViewer(zoom, angle);
|
||||||
viewer.setSet(set);
|
viewer.setSet(set);
|
||||||
viewer.setCard(card);
|
viewer.setCard(card);
|
||||||
@@ -97,8 +98,59 @@ Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, cons
|
|||||||
// draw
|
// draw
|
||||||
viewer.draw(dc);
|
viewer.draw(dc);
|
||||||
dc.SelectObject(wxNullBitmap);
|
dc.SelectObject(wxNullBitmap);
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put multiple card images into one bitmap
|
||||||
|
Bitmap export_bitmap(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle = 0.0) {
|
||||||
|
if (!set) throw Error(_("no set"));
|
||||||
|
vector<Bitmap> bitmaps;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
double lowest_dpi = 1200.0;
|
||||||
|
if (scale_to_lowest_dpi) {
|
||||||
|
FOR_EACH(card, cards) {
|
||||||
|
lowest_dpi = min(lowest_dpi, set->stylesheetFor(card).card_dpi);
|
||||||
|
}
|
||||||
|
lowest_dpi = max(lowest_dpi, 150.0);
|
||||||
|
}
|
||||||
|
// Draw card bitmaps
|
||||||
|
FOR_EACH(card, cards) {
|
||||||
|
double scaled_zoom = zoom;
|
||||||
|
if (scale_to_lowest_dpi) {
|
||||||
|
double dpi = max(set->stylesheetFor(card).card_dpi, 150.0);
|
||||||
|
scaled_zoom *= lowest_dpi / dpi;
|
||||||
|
}
|
||||||
|
UnzoomedDataViewer viewer = UnzoomedDataViewer(scaled_zoom, angle);
|
||||||
|
viewer.setSet(set);
|
||||||
|
viewer.setCard(card);
|
||||||
|
RealSize size = viewer.getRotation().getExternalSize();
|
||||||
|
Bitmap bitmap((int)size.width, (int)size.height);
|
||||||
|
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||||
|
wxMemoryDC bufferDC;
|
||||||
|
bufferDC.SelectObject(bitmap);
|
||||||
|
clearDC(bufferDC, *wxWHITE_BRUSH);
|
||||||
|
viewer.draw(bufferDC);
|
||||||
|
bufferDC.SelectObject(wxNullBitmap);
|
||||||
|
width += (int)size.width;
|
||||||
|
height = max(height, (int)size.height);
|
||||||
|
bitmaps.push_back(bitmap);
|
||||||
|
}
|
||||||
|
// Draw global bitmap
|
||||||
|
Bitmap global_bitmap(width + (bitmaps.size()-1) * padding, height);
|
||||||
|
if (!global_bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||||
|
wxMemoryDC globalDC;
|
||||||
|
globalDC.SelectObject(global_bitmap);
|
||||||
|
clearDC(globalDC, *wxWHITE_BRUSH);
|
||||||
|
int offset = 0;
|
||||||
|
FOR_EACH(bitmap, bitmaps) {
|
||||||
|
globalDC.SetDeviceOrigin(offset, 0);
|
||||||
|
globalDC.DrawBitmap(bitmap, 0, 0);
|
||||||
|
offset += bitmap.GetWidth() + padding;
|
||||||
|
}
|
||||||
|
globalDC.SelectObject(wxNullBitmap);
|
||||||
|
return global_bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Multiple card export
|
// ----------------------------------------------------------------------------- : Multiple card export
|
||||||
|
|
||||||
|
|||||||
+21
-20
@@ -48,6 +48,7 @@ IMPLEMENT_REFLECTION(Game) {
|
|||||||
}
|
}
|
||||||
REFLECT_NO_SCRIPT(default_set_style);
|
REFLECT_NO_SCRIPT(default_set_style);
|
||||||
REFLECT_NO_SCRIPT(card_fields);
|
REFLECT_NO_SCRIPT(card_fields);
|
||||||
|
REFLECT_NO_SCRIPT(card_links);
|
||||||
REFLECT_NO_SCRIPT(card_list_color_script);
|
REFLECT_NO_SCRIPT(card_list_color_script);
|
||||||
REFLECT_NO_SCRIPT(import_script);
|
REFLECT_NO_SCRIPT(import_script);
|
||||||
REFLECT_NO_SCRIPT(json_paths);
|
REFLECT_NO_SCRIPT(json_paths);
|
||||||
@@ -95,26 +96,26 @@ void Game::validate(Version v) {
|
|||||||
pack->filter = OptionalScript(_("true"));
|
pack->filter = OptionalScript(_("true"));
|
||||||
pack->select = SELECT_NO_REPLACE;
|
pack->select = SELECT_NO_REPLACE;
|
||||||
pack_types.push_back(pack);
|
pack_types.push_back(pack);
|
||||||
}
|
}
|
||||||
// alternate card field names map
|
// alternate card field names map
|
||||||
for (auto it = card_fields.begin(); it != card_fields.end(); ++it) {
|
for (auto it = card_fields.begin(); it != card_fields.end(); ++it) {
|
||||||
FieldP field = *it;
|
FieldP field = *it;
|
||||||
String unified_name = unified_form(field->name);
|
String unified_name = unified_form(field->name);
|
||||||
if (card_fields_alt_names.count(unified_name)) {
|
if (card_fields_alt_names.count(unified_name)) {
|
||||||
queue_message(MESSAGE_WARNING, _("Duplicate alternate card field name: ") + unified_name);
|
queue_message(MESSAGE_WARNING, _("Duplicate alternate card field name: ") + unified_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
card_fields_alt_names.emplace(unified_name, field->name);
|
card_fields_alt_names.emplace(unified_name, field->name);
|
||||||
}
|
}
|
||||||
//String column_name = field->card_list_name.get();
|
//String column_name = field->card_list_name.get();
|
||||||
//card_fields_alt_names.emplace(unified_form(column_name), field->name);
|
//card_fields_alt_names.emplace(unified_form(column_name), field->name);
|
||||||
for (auto it2 = field->alt_names.begin(); it2 != field->alt_names.end(); ++it2) {
|
for (auto it2 = field->alt_names.begin(); it2 != field->alt_names.end(); ++it2) {
|
||||||
unified_name = unified_form(*it2);
|
unified_name = unified_form(*it2);
|
||||||
if (card_fields_alt_names.count(unified_name)) {
|
if (card_fields_alt_names.count(unified_name)) {
|
||||||
queue_message(MESSAGE_WARNING, _("Duplicate alternate card field name: ") + unified_name);
|
queue_message(MESSAGE_WARNING, _("Duplicate alternate card field name: ") + unified_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
card_fields_alt_names.emplace(unified_name, field->name);
|
card_fields_alt_names.emplace(unified_name, field->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,7 +139,7 @@ void Game::initCardListColorScript() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// special behaviour of reading/writing GamePs: only read/write the name
|
// special behaviour of reading/writing GamePs: only read/write the name
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -12,7 +12,7 @@
|
|||||||
#include <util/io/package.hpp>
|
#include <util/io/package.hpp>
|
||||||
#include <script/scriptable.hpp>
|
#include <script/scriptable.hpp>
|
||||||
#include <script/dependency.hpp>
|
#include <script/dependency.hpp>
|
||||||
#include <util/dynamic_arg.hpp>
|
#include <util/dynamic_arg.hpp>
|
||||||
|
|
||||||
DECLARE_POINTER_TYPE(Field);
|
DECLARE_POINTER_TYPE(Field);
|
||||||
DECLARE_POINTER_TYPE(Style);
|
DECLARE_POINTER_TYPE(Style);
|
||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
vector<FieldP> set_fields; ///< Fields for set information
|
vector<FieldP> set_fields; ///< Fields for set information
|
||||||
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
|
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
|
||||||
vector<FieldP> card_fields; ///< Fields on each card
|
vector<FieldP> card_fields; ///< Fields on each card
|
||||||
|
vector<String> card_links; ///< Possible links between cards
|
||||||
OptionalScript card_list_color_script; ///< Script that determines the color of items in the card list
|
OptionalScript card_list_color_script; ///< Script that determines the color of items in the card list
|
||||||
OptionalScript import_script; ///< Script applied as the last step of the new_card function
|
OptionalScript import_script; ///< Script applied as the last step of the new_card function
|
||||||
vector<String> json_paths; ///< Paths inside JSON files to find the card array
|
vector<String> json_paths; ///< Paths inside JSON files to find the card array
|
||||||
@@ -50,8 +51,7 @@ public:
|
|||||||
vector<WordListP> word_lists; ///< Word lists for editing with a drop down list
|
vector<WordListP> word_lists; ///< Word lists for editing with a drop down list
|
||||||
vector<AddCardsScriptP> add_cards_scripts; ///< Scripts for adding multiple cards to the set
|
vector<AddCardsScriptP> add_cards_scripts; ///< Scripts for adding multiple cards to the set
|
||||||
vector<AutoReplaceP> auto_replaces; ///< Things to autoreplace in textboxes
|
vector<AutoReplaceP> auto_replaces; ///< Things to autoreplace in textboxes
|
||||||
map<String,String> card_fields_alt_names; ///< Other names that fields might go by, for example in CSV files
|
map<String,String> card_fields_alt_names; ///< Other names that fields might go by, for example in CSV files
|
||||||
|
|
||||||
bool has_keywords; ///< Does this game use keywords?
|
bool has_keywords; ///< Does this game use keywords?
|
||||||
OptionalScript keyword_match_script; ///< For the keyword editor
|
OptionalScript keyword_match_script; ///< For the keyword editor
|
||||||
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
|
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
|
||||||
|
|||||||
+4
-4
@@ -118,8 +118,8 @@ String tr(const Package& pkg, const String& subcat, const String& key, DefaultLo
|
|||||||
loc = find_wildcard_and_set(the_locale->package_translations, pkg.relativeFilename());
|
loc = find_wildcard_and_set(the_locale->package_translations, pkg.relativeFilename());
|
||||||
}
|
}
|
||||||
return loc->tr(subcat, key, def);
|
return loc->tr(subcat, key, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
String tr(const String& pkg_relative_filename, const String& key, DefaultLocaleFun def) {
|
String tr(const String& pkg_relative_filename, const String& key, DefaultLocaleFun def) {
|
||||||
if (!the_locale) return def(key);
|
if (!the_locale) return def(key);
|
||||||
SubLocaleP loc = the_locale->package_translations[pkg_relative_filename];
|
SubLocaleP loc = the_locale->package_translations[pkg_relative_filename];
|
||||||
@@ -127,8 +127,8 @@ String tr(const String& pkg_relative_filename, const String& key, DefaultLocaleF
|
|||||||
loc = find_wildcard_and_set(the_locale->package_translations, pkg_relative_filename);
|
loc = find_wildcard_and_set(the_locale->package_translations, pkg_relative_filename);
|
||||||
}
|
}
|
||||||
return loc->tr(key, def);
|
return loc->tr(key, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
String tr(const String& pkg_relative_filename, const String& subcat, const String& key, DefaultLocaleFun def) {
|
String tr(const String& pkg_relative_filename, const String& subcat, const String& key, DefaultLocaleFun def) {
|
||||||
if (!the_locale) return def(key);
|
if (!the_locale) return def(key);
|
||||||
SubLocaleP loc = the_locale->package_translations[pkg_relative_filename];
|
SubLocaleP loc = the_locale->package_translations[pkg_relative_filename];
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ StyleSheetSettings::StyleSheetSettings()
|
|||||||
, card_angle (0, true)
|
, card_angle (0, true)
|
||||||
, card_anti_alias (true, true)
|
, card_anti_alias (true, true)
|
||||||
, card_borders (true, true)
|
, card_borders (true, true)
|
||||||
, card_draw_editing (true, true)
|
, card_draw_editing (true, true)
|
||||||
, card_normal_export (true, true)
|
, card_normal_export (true, true)
|
||||||
, card_spellcheck_enabled(true, true)
|
, card_spellcheck_enabled(true, true)
|
||||||
{}
|
{}
|
||||||
@@ -137,7 +137,7 @@ void StyleSheetSettings::useDefault(const StyleSheetSettings& ss) {
|
|||||||
if (card_angle .isDefault()) card_angle .assignDefault(ss.card_angle);
|
if (card_angle .isDefault()) card_angle .assignDefault(ss.card_angle);
|
||||||
if (card_anti_alias .isDefault()) card_anti_alias .assignDefault(ss.card_anti_alias);
|
if (card_anti_alias .isDefault()) card_anti_alias .assignDefault(ss.card_anti_alias);
|
||||||
if (card_borders .isDefault()) card_borders .assignDefault(ss.card_borders);
|
if (card_borders .isDefault()) card_borders .assignDefault(ss.card_borders);
|
||||||
if (card_draw_editing .isDefault()) card_draw_editing .assignDefault(ss.card_draw_editing);
|
if (card_draw_editing .isDefault()) card_draw_editing .assignDefault(ss.card_draw_editing);
|
||||||
if (card_normal_export .isDefault()) card_normal_export .assignDefault(ss.card_normal_export);
|
if (card_normal_export .isDefault()) card_normal_export .assignDefault(ss.card_normal_export);
|
||||||
if (card_spellcheck_enabled.isDefault()) card_spellcheck_enabled.assignDefault(ss.card_spellcheck_enabled);
|
if (card_spellcheck_enabled.isDefault()) card_spellcheck_enabled.assignDefault(ss.card_spellcheck_enabled);
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(StyleSheetSettings) {
|
|||||||
REFLECT(card_angle);
|
REFLECT(card_angle);
|
||||||
REFLECT(card_anti_alias);
|
REFLECT(card_anti_alias);
|
||||||
REFLECT(card_borders);
|
REFLECT(card_borders);
|
||||||
REFLECT(card_draw_editing);
|
REFLECT(card_draw_editing);
|
||||||
REFLECT(card_normal_export);
|
REFLECT(card_normal_export);
|
||||||
REFLECT(card_spellcheck_enabled);
|
REFLECT(card_spellcheck_enabled);
|
||||||
}
|
}
|
||||||
@@ -225,8 +225,8 @@ ColumnSettings& Settings::columnSettingsFor(const Game& game, const Field& field
|
|||||||
}
|
}
|
||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
StyleSheetSettings& Settings::stylesheetSettingsFor(const StyleSheet& stylesheet) {
|
StyleSheetSettings& Settings::stylesheetSettingsFor(const StyleSheet& stylesheet) {
|
||||||
// Use the canonical form here since the stylesheet name will be used as a stored key.
|
// Use the canonical form here since the stylesheet name will be used as a stored key.
|
||||||
// This does introduce the possibility of collision if two stylesheets return the same value canonically, but I think that's just a necessary risk.
|
// This does introduce the possibility of collision if two stylesheets return the same value canonically, but I think that's just a necessary risk.
|
||||||
StyleSheetSettingsP& ss = stylesheet_settings[canonical_name_form(stylesheet.name())];
|
StyleSheetSettingsP& ss = stylesheet_settings[canonical_name_form(stylesheet.name())];
|
||||||
if (!ss) ss = make_intrusive<StyleSheetSettings>();
|
if (!ss) ss = make_intrusive<StyleSheetSettings>();
|
||||||
|
|||||||
@@ -195,10 +195,10 @@ public:
|
|||||||
|
|
||||||
// --------------------------------------------------- : Special game stuff
|
// --------------------------------------------------- : Special game stuff
|
||||||
String apprentice_location;
|
String apprentice_location;
|
||||||
|
|
||||||
// --------------------------------------------------- : Internal settings
|
// --------------------------------------------------- : Internal settings
|
||||||
double internal_scale;
|
double internal_scale;
|
||||||
bool internal_image_extension;
|
bool internal_image_extension;
|
||||||
|
|
||||||
// --------------------------------------------------- : Update checking
|
// --------------------------------------------------- : Update checking
|
||||||
#if USE_OLD_STYLE_UPDATE_CHECKER
|
#if USE_OLD_STYLE_UPDATE_CHECKER
|
||||||
|
|||||||
+6
-11
@@ -38,13 +38,13 @@ StyleSheetP StyleSheet::byGameAndName(const Game& game, const String& name) {
|
|||||||
}
|
}
|
||||||
} catch (PackageNotFoundError& e) {
|
} catch (PackageNotFoundError& e) {
|
||||||
queue_message(MESSAGE_ERROR, _("Missing stylesheet: ") + full_name);
|
queue_message(MESSAGE_ERROR, _("Missing stylesheet: ") + full_name);
|
||||||
|
|
||||||
// This causes a freeze when the set contains two cards that use the same missing StyleSheet, and the second one has styling_data
|
// This causes a freeze when the set contains two cards that use the same missing StyleSheet, and the second one has styling_data
|
||||||
// Also, it's probably better to ask the user for an alternative for each missing StyleSheet individually
|
// Also, it's probably better to ask the user for an alternative for each missing StyleSheet individually
|
||||||
//if (stylesheet_for_reading()) {
|
//if (stylesheet_for_reading()) {
|
||||||
// // we already have a stylesheet higher up, so just return a null pointer
|
// // we already have a stylesheet higher up, so just return a null pointer
|
||||||
// return StyleSheetP();
|
// return StyleSheetP();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// load an alternative stylesheet
|
// load an alternative stylesheet
|
||||||
StyleSheetP ss = select_stylesheet(game, name);
|
StyleSheetP ss = select_stylesheet(game, name);
|
||||||
@@ -103,7 +103,7 @@ IMPLEMENT_REFLECTION(StyleSheet) {
|
|||||||
REFLECT(card_width);
|
REFLECT(card_width);
|
||||||
REFLECT(card_height);
|
REFLECT(card_height);
|
||||||
REFLECT(card_dpi);
|
REFLECT(card_dpi);
|
||||||
REFLECT(card_background);
|
REFLECT(card_background);
|
||||||
REFLECT(card_regions);
|
REFLECT(card_regions);
|
||||||
REFLECT(init_script);
|
REFLECT(init_script);
|
||||||
// styling
|
// styling
|
||||||
@@ -122,12 +122,7 @@ IMPLEMENT_REFLECTION(StyleSheet) {
|
|||||||
// extra card fields
|
// extra card fields
|
||||||
REFLECT(extra_card_fields);
|
REFLECT(extra_card_fields);
|
||||||
REFLECT_IF_READING {
|
REFLECT_IF_READING {
|
||||||
if (extra_card_style.init(extra_card_fields)) {
|
extra_card_style.init(extra_card_fields);
|
||||||
// if a value is not editable, don't save it
|
|
||||||
FOR_EACH(f, extra_card_fields) {
|
|
||||||
if (!f->editable) f->save_value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
REFLECT(extra_card_style);
|
REFLECT(extra_card_style);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,16 @@
|
|||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <util/io/package.hpp>
|
#include <util/io/package.hpp>
|
||||||
#include <util/real_point.hpp>
|
#include <util/real_point.hpp>
|
||||||
#include <script/scriptable.hpp>
|
#include <script/scriptable.hpp>
|
||||||
// This isn't strictly needed for this file,
|
// This isn't strictly needed for this file,
|
||||||
// but CardRegion needs to be referenced from _somewhere_ in the codebase for compilation reasons.
|
// but CardRegion needs to be referenced from _somewhere_ in the codebase for compilation reasons.
|
||||||
// Eventually if somewhere else is using the type then this can be removed.
|
// Eventually if somewhere else is using the type then this can be removed.
|
||||||
#include <data/card_region.hpp>
|
#include <data/card_region.hpp>
|
||||||
|
|
||||||
DECLARE_POINTER_TYPE(Game);
|
DECLARE_POINTER_TYPE(Game);
|
||||||
DECLARE_POINTER_TYPE(StyleSheet);
|
DECLARE_POINTER_TYPE(StyleSheet);
|
||||||
DECLARE_POINTER_TYPE(Field);
|
DECLARE_POINTER_TYPE(Field);
|
||||||
DECLARE_POINTER_TYPE(Style);
|
DECLARE_POINTER_TYPE(Style);
|
||||||
DECLARE_POINTER_TYPE(CardRegion);
|
DECLARE_POINTER_TYPE(CardRegion);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : StyleSheet
|
// ----------------------------------------------------------------------------- : StyleSheet
|
||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
double card_width; ///< The width of a card in pixels
|
double card_width; ///< The width of a card in pixels
|
||||||
double card_height; ///< The height of a card in pixels
|
double card_height; ///< The height of a card in pixels
|
||||||
double card_dpi; ///< The resolution of a card in dots per inch
|
double card_dpi; ///< The resolution of a card in dots per inch
|
||||||
Color card_background; ///< The background color of cards
|
Color card_background; ///< The background color of cards
|
||||||
vector<CardRegionP> card_regions;
|
vector<CardRegionP> card_regions;
|
||||||
/// The styling for card fields
|
/// The styling for card fields
|
||||||
/** The indices should correspond to the card_fields in the Game */
|
/** The indices should correspond to the card_fields in the Game */
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ void SymbolFont::getCharInfo(RotatedDC& dc, double font_size, const SplitSymbols
|
|||||||
|
|
||||||
RealSize SymbolFont::symbolSize(double font_size, const DrawableSymbol& sym) {
|
RealSize SymbolFont::symbolSize(double font_size, const DrawableSymbol& sym) {
|
||||||
if (sym.symbol) {
|
if (sym.symbol) {
|
||||||
return add_diagonal(sym.symbol->size(*this, font_size), spacing);
|
return add_diagonal(sym.symbol->size(*this, font_size), spacingSize(font_size));
|
||||||
} else {
|
} else {
|
||||||
return defaultSymbolSize(font_size);
|
return defaultSymbolSize(font_size);
|
||||||
}
|
}
|
||||||
@@ -403,12 +403,15 @@ RealSize SymbolFont::symbolSize(double font_size, const DrawableSymbol& sym) {
|
|||||||
RealSize SymbolFont::defaultSymbolSize(double font_size) {
|
RealSize SymbolFont::defaultSymbolSize(double font_size) {
|
||||||
SymbolInFont* def = defaultSymbol();
|
SymbolInFont* def = defaultSymbol();
|
||||||
if (def) {
|
if (def) {
|
||||||
return add_diagonal(def->size(*this, font_size), spacing);
|
return add_diagonal(def->size(*this, font_size), spacingSize(font_size));
|
||||||
} else {
|
} else {
|
||||||
return add_diagonal(RealSize(1,1), spacing);
|
return add_diagonal(RealSize(1,1), spacingSize(font_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RealSize SymbolFont::spacingSize(double font_size) {
|
||||||
|
return RealSize(spacing.width * font_size / 15.0, spacing.height * font_size / 15.0);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : InsertSymbolMenu
|
// ----------------------------------------------------------------------------- : InsertSymbolMenu
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
double img_size; ///< Font size that the images use
|
double img_size; ///< Font size that the images use
|
||||||
RealSize spacing; ///< Spacing between sybmols (for the default font size)
|
RealSize spacing; ///< Spacing between sybmols, in pixels, for a font size of 15
|
||||||
// writing text
|
// writing text
|
||||||
bool scale_text; ///< Should text be scaled down to fit in a symbol?
|
bool scale_text; ///< Should text be scaled down to fit in a symbol?
|
||||||
InsertSymbolMenuP insert_symbol_menu;
|
InsertSymbolMenuP insert_symbol_menu;
|
||||||
@@ -107,6 +107,9 @@ public:
|
|||||||
/// The default size of symbols, including spacing
|
/// The default size of symbols, including spacing
|
||||||
RealSize defaultSymbolSize(double font_size);
|
RealSize defaultSymbolSize(double font_size);
|
||||||
|
|
||||||
|
/// The spacing between symbols, accounting for font size
|
||||||
|
RealSize SymbolFont::spacingSize(double font_size);
|
||||||
|
|
||||||
DECLARE_REFLECTION();
|
DECLARE_REFLECTION();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ void linear_blend(Image& img1, const Image& img2, double x1,double y1, double x2
|
|||||||
data1 += 3;
|
data1 += 3;
|
||||||
data2 += 3;
|
data2 += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blend Alpha for the two images.
|
// Blend Alpha for the two images.
|
||||||
if (img1.HasAlpha() && img2.HasAlpha()) {
|
if (img1.HasAlpha() && img2.HasAlpha()) {
|
||||||
Byte *alpha1 = img1.GetAlpha(), *alpha2 = img2.GetAlpha();
|
Byte *alpha1 = img1.GetAlpha(), *alpha2 = img2.GetAlpha();
|
||||||
for (int y = 0; y < height; ++y) {
|
for (int y = 0; y < height; ++y) {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ IMPLEMENT_REFLECTION_ENUM(ImageCombine) {
|
|||||||
VALUE_N("greater than 235", COMBINE_GREATER_THAN_235);
|
VALUE_N("greater than 235", COMBINE_GREATER_THAN_235);
|
||||||
VALUE_N("greater than 240", COMBINE_GREATER_THAN_240);
|
VALUE_N("greater than 240", COMBINE_GREATER_THAN_240);
|
||||||
VALUE_N("greater than 245", COMBINE_GREATER_THAN_245);
|
VALUE_N("greater than 245", COMBINE_GREATER_THAN_245);
|
||||||
VALUE_N("greater than 250", COMBINE_GREATER_THAN_250);
|
VALUE_N("greater than 250", COMBINE_GREATER_THAN_250);
|
||||||
VALUE_N("smaller than 5", COMBINE_SMALLER_THAN_5);
|
VALUE_N("smaller than 5", COMBINE_SMALLER_THAN_5);
|
||||||
VALUE_N("smaller than 10", COMBINE_SMALLER_THAN_10);
|
VALUE_N("smaller than 10", COMBINE_SMALLER_THAN_10);
|
||||||
VALUE_N("smaller than 15", COMBINE_SMALLER_THAN_15);
|
VALUE_N("smaller than 15", COMBINE_SMALLER_THAN_15);
|
||||||
@@ -237,7 +237,7 @@ COMBINE_FUN(COMBINE_GREATER_THAN_230, a > 230 ? b : a)
|
|||||||
COMBINE_FUN(COMBINE_GREATER_THAN_235, a > 235 ? b : a)
|
COMBINE_FUN(COMBINE_GREATER_THAN_235, a > 235 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_GREATER_THAN_240, a > 240 ? b : a)
|
COMBINE_FUN(COMBINE_GREATER_THAN_240, a > 240 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_GREATER_THAN_245, a > 245 ? b : a)
|
COMBINE_FUN(COMBINE_GREATER_THAN_245, a > 245 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_GREATER_THAN_250, a > 250 ? b : a)
|
COMBINE_FUN(COMBINE_GREATER_THAN_250, a > 250 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_5, a < 5 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_5, a < 5 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_10, a < 10 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_10, a < 10 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_15, a < 15 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_15, a < 15 ? b : a)
|
||||||
@@ -287,7 +287,7 @@ COMBINE_FUN(COMBINE_SMALLER_THAN_230, a < 230 ? b : a)
|
|||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_235, a < 235 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_235, a < 235 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_240, a < 240 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_240, a < 240 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_245, a < 245 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_245, a < 245 ? b : a)
|
||||||
COMBINE_FUN(COMBINE_SMALLER_THAN_250, a < 250 ? b : a)
|
COMBINE_FUN(COMBINE_SMALLER_THAN_250, a < 250 ? b : a)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Combining
|
// ----------------------------------------------------------------------------- : Combining
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ void combine_image_do(Image& a, Image b) {
|
|||||||
void combine_image(Image& a, const Image& b, ImageCombine combine) {
|
void combine_image(Image& a, const Image& b, ImageCombine combine) {
|
||||||
// Images must have same size
|
// Images must have same size
|
||||||
if (a.GetWidth() != b.GetWidth() || a.GetHeight() != b.GetHeight()) {
|
if (a.GetWidth() != b.GetWidth() || a.GetHeight() != b.GetHeight()) {
|
||||||
throw Error(_ERROR_("images used for combine blending must have the same size"));
|
throw Error(_ERROR_("images used for combine blending must have the same size"));
|
||||||
}
|
}
|
||||||
// Copy alpha channel?
|
// Copy alpha channel?
|
||||||
if (b.HasAlpha()) {
|
if (b.HasAlpha()) {
|
||||||
@@ -392,7 +392,7 @@ void combine_image(Image& a, const Image& b, ImageCombine combine) {
|
|||||||
DISPATCH(COMBINE_GREATER_THAN_235);
|
DISPATCH(COMBINE_GREATER_THAN_235);
|
||||||
DISPATCH(COMBINE_GREATER_THAN_240);
|
DISPATCH(COMBINE_GREATER_THAN_240);
|
||||||
DISPATCH(COMBINE_GREATER_THAN_245);
|
DISPATCH(COMBINE_GREATER_THAN_245);
|
||||||
DISPATCH(COMBINE_GREATER_THAN_250);
|
DISPATCH(COMBINE_GREATER_THAN_250);
|
||||||
DISPATCH(COMBINE_SMALLER_THAN_5);
|
DISPATCH(COMBINE_SMALLER_THAN_5);
|
||||||
DISPATCH(COMBINE_SMALLER_THAN_10);
|
DISPATCH(COMBINE_SMALLER_THAN_10);
|
||||||
DISPATCH(COMBINE_SMALLER_THAN_15);
|
DISPATCH(COMBINE_SMALLER_THAN_15);
|
||||||
|
|||||||
+133
-133
@@ -14,7 +14,7 @@
|
|||||||
#include <data/field/symbol.hpp>
|
#include <data/field/symbol.hpp>
|
||||||
#include <render/symbol/filter.hpp>
|
#include <render/symbol/filter.hpp>
|
||||||
#include <gui/util.hpp> // load_resource_image
|
#include <gui/util.hpp> // load_resource_image
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : GeneratedImage
|
// ----------------------------------------------------------------------------- : GeneratedImage
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ bool EnlargeImage::operator == (const GeneratedImage& that) const {
|
|||||||
// ----------------------------------------------------------------------------- : ResizeImage
|
// ----------------------------------------------------------------------------- : ResizeImage
|
||||||
|
|
||||||
Image ResizeImage::generate(const Options& opt) const {
|
Image ResizeImage::generate(const Options& opt) const {
|
||||||
Image img = image->generate(opt);
|
Image img = image->generate(opt);
|
||||||
return resample(img, width, height);
|
return resample(img, width, height);
|
||||||
}
|
}
|
||||||
bool ResizeImage::operator == (const GeneratedImage& that) const {
|
bool ResizeImage::operator == (const GeneratedImage& that) const {
|
||||||
@@ -321,16 +321,16 @@ bool ResizeImage::operator == (const GeneratedImage& that) const {
|
|||||||
// ----------------------------------------------------------------------------- : BleedEdgedImage
|
// ----------------------------------------------------------------------------- : BleedEdgedImage
|
||||||
|
|
||||||
Image BleedEdgedImage::generate(const Options& opt) const {
|
Image BleedEdgedImage::generate(const Options& opt) const {
|
||||||
// create enlarged image
|
// create enlarged image
|
||||||
Image base_img = base_image->generate(opt);
|
Image base_img = base_image->generate(opt);
|
||||||
int w = base_img.GetWidth(), h = base_img.GetHeight();
|
int w = base_img.GetWidth(), h = base_img.GetHeight();
|
||||||
if (w <= 0 || h <= 0) {
|
if (w <= 0 || h <= 0) {
|
||||||
queue_message(MESSAGE_ERROR, _("Cannot add bleed edge to empty image"));
|
queue_message(MESSAGE_ERROR, _("Cannot add bleed edge to empty image"));
|
||||||
return base_img;
|
return base_img;
|
||||||
}
|
}
|
||||||
bool is_landscape = w > h;
|
bool is_landscape = w > h;
|
||||||
int dw = int(w * (horizontal_size > 0.0 ? horizontal_size : is_landscape ? 0.037 : 0.048));
|
int dw = int(w * (horizontal_size > 0.0 ? horizontal_size : is_landscape ? 0.037 : 0.048));
|
||||||
int dh = int(h * (vertical_size > 0.0 ? vertical_size : is_landscape ? 0.048 : 0.037));
|
int dh = int(h * (vertical_size > 0.0 ? vertical_size : is_landscape ? 0.048 : 0.037));
|
||||||
if (dw <= 0 && dh <= 0) {
|
if (dw <= 0 && dh <= 0) {
|
||||||
return base_img;
|
return base_img;
|
||||||
}
|
}
|
||||||
@@ -339,119 +339,119 @@ Image BleedEdgedImage::generate(const Options& opt) const {
|
|||||||
Image img = wxImage(width, height, false);
|
Image img = wxImage(width, height, false);
|
||||||
img.InitAlpha();
|
img.InitAlpha();
|
||||||
Byte* data = img.GetData();
|
Byte* data = img.GetData();
|
||||||
Byte* alpha = img.GetAlpha();
|
Byte* alpha = img.GetAlpha();
|
||||||
// fill with background color
|
// fill with background color
|
||||||
for (UInt i = 0; i < size; ++i) {
|
for (UInt i = 0; i < size; ++i) {
|
||||||
data[3 * i + 0] = background_color.Red();
|
data[3 * i + 0] = background_color.Red();
|
||||||
data[3 * i + 1] = background_color.Green();
|
data[3 * i + 1] = background_color.Green();
|
||||||
data[3 * i + 2] = background_color.Blue();
|
data[3 * i + 2] = background_color.Blue();
|
||||||
alpha[i] = background_color.Alpha();
|
alpha[i] = background_color.Alpha();
|
||||||
}
|
}
|
||||||
// paste original image
|
// paste original image
|
||||||
img.Paste(base_img, dw, dh, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
img.Paste(base_img, dw, dh, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||||
// fill top left corner
|
// fill top left corner
|
||||||
int pixel;
|
int pixel;
|
||||||
int x_start = 0;
|
int x_start = 0;
|
||||||
int y_start = 0;
|
int y_start = 0;
|
||||||
int ref = dw + dh * width;
|
int ref = dw + dh * width;
|
||||||
for (int y = 0; y < dh; ++y) {
|
for (int y = 0; y < dh; ++y) {
|
||||||
for (int x = 0; x < dw; ++x) {
|
for (int x = 0; x < dw; ++x) {
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
alpha[pixel] = alpha[ref];
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
|
||||||
}
|
|
||||||
// fill top right corner
|
|
||||||
x_start = width - dw;
|
|
||||||
y_start = 0;
|
|
||||||
ref = x_start - 1 + dh * width;
|
|
||||||
for (int y = 0; y < dh; ++y) {
|
|
||||||
for (int x = 0; x < dw; ++x) {
|
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
|
||||||
alpha[pixel] = alpha[ref];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fill bottom left corner
|
|
||||||
x_start = 0;
|
|
||||||
y_start = height - dh;
|
|
||||||
ref = dw + (y_start - 1) * width;
|
|
||||||
for (int y = 0; y < dh; ++y) {
|
|
||||||
for (int x = 0; x < dw; ++x) {
|
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
|
||||||
alpha[pixel] = alpha[ref];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fill bottom right corner
|
// fill top right corner
|
||||||
x_start = width - dw;
|
x_start = width - dw;
|
||||||
y_start = height - dh;
|
y_start = 0;
|
||||||
|
ref = x_start - 1 + dh * width;
|
||||||
|
for (int y = 0; y < dh; ++y) {
|
||||||
|
for (int x = 0; x < dw; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill bottom left corner
|
||||||
|
x_start = 0;
|
||||||
|
y_start = height - dh;
|
||||||
|
ref = dw + (y_start - 1) * width;
|
||||||
|
for (int y = 0; y < dh; ++y) {
|
||||||
|
for (int x = 0; x < dw; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill bottom right corner
|
||||||
|
x_start = width - dw;
|
||||||
|
y_start = height - dh;
|
||||||
ref = (x_start - 1) + (y_start - 1) * width;
|
ref = (x_start - 1) + (y_start - 1) * width;
|
||||||
for (int y = 0; y < dh; ++y) {
|
for (int y = 0; y < dh; ++y) {
|
||||||
for (int x = 0; x < dw; ++x) {
|
for (int x = 0; x < dw; ++x) {
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
alpha[pixel] = alpha[ref];
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fill left border
|
// fill left border
|
||||||
x_start = 0;
|
x_start = 0;
|
||||||
y_start = dh;
|
y_start = dh;
|
||||||
for (int y = 0; y < height - dh - dh; ++y) {
|
for (int y = 0; y < height - dh - dh; ++y) {
|
||||||
ref = dw + (y_start + y) * width;
|
ref = dw + (y_start + y) * width;
|
||||||
for (int x = 0; x < dw; ++x) {
|
for (int x = 0; x < dw; ++x) {
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
alpha[pixel] = alpha[ref];
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fill top border
|
// fill top border
|
||||||
x_start = dw;
|
x_start = dw;
|
||||||
y_start = 0;
|
y_start = 0;
|
||||||
for (int y = 0; y < dh; ++y) {
|
for (int y = 0; y < dh; ++y) {
|
||||||
for (int x = 0; x < width - dw - dw; ++x) {
|
for (int x = 0; x < width - dw - dw; ++x) {
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
ref = x_start + x + dh * width;
|
ref = x_start + x + dh * width;
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
alpha[pixel] = alpha[ref];
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fill right border
|
// fill right border
|
||||||
x_start = width - dw;
|
x_start = width - dw;
|
||||||
y_start = dh;
|
y_start = dh;
|
||||||
for (int y = 0; y < height - dh - dh; ++y) {
|
for (int y = 0; y < height - dh - dh; ++y) {
|
||||||
ref = width - dw - 1 + (y_start + y) * width;
|
ref = width - dw - 1 + (y_start + y) * width;
|
||||||
for (int x = 0; x < dw; ++x) {
|
for (int x = 0; x < dw; ++x) {
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
alpha[pixel] = alpha[ref];
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fill bottom border
|
// fill bottom border
|
||||||
x_start = dw;
|
x_start = dw;
|
||||||
y_start = height - dh;
|
y_start = height - dh;
|
||||||
for (int y = 0; y < dh; ++y) {
|
for (int y = 0; y < dh; ++y) {
|
||||||
for (int x = 0; x < width - dw - dw; ++x) {
|
for (int x = 0; x < width - dw - dw; ++x) {
|
||||||
pixel = x_start + x + (y_start + y) * width;
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
ref = x_start + x + (height - dh - 1) * width;
|
ref = x_start + x + (height - dh - 1) * width;
|
||||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||||
alpha[pixel] = alpha[ref];
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// done
|
// done
|
||||||
@@ -621,7 +621,7 @@ Image PackagedImage::generate(const Options& opt) const {
|
|||||||
if (img.HasMask()) img.InitAlpha(); // we can't handle masks
|
if (img.HasMask()) img.InitAlpha(); // we can't handle masks
|
||||||
return img;
|
return img;
|
||||||
} else {
|
} else {
|
||||||
throw ScriptError(_("Unable to load image '") + filename + _("' from '" + opt.package->name() + _("'")));
|
throw ScriptError(_("Unable to load image '") + filename + _("' from '") + opt.package->name() + _("'"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool PackagedImage::operator == (const GeneratedImage& that) const {
|
bool PackagedImage::operator == (const GeneratedImage& that) const {
|
||||||
@@ -642,17 +642,17 @@ Image BuiltInImage::generate(const Options& opt) const {
|
|||||||
bool BuiltInImage::operator == (const GeneratedImage& that) const {
|
bool BuiltInImage::operator == (const GeneratedImage& that) const {
|
||||||
const BuiltInImage* that2 = dynamic_cast<const BuiltInImage*>(&that);
|
const BuiltInImage* that2 = dynamic_cast<const BuiltInImage*>(&that);
|
||||||
return that2 && name == that2->name;
|
return that2 && name == that2->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ArbitraryImage
|
// ----------------------------------------------------------------------------- : ArbitraryImage
|
||||||
|
|
||||||
Image ArbitraryImage::generate(const Options& opt) const {
|
Image ArbitraryImage::generate(const Options& opt) const {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
bool ArbitraryImage::operator == (const GeneratedImage& that) const {
|
bool ArbitraryImage::operator == (const GeneratedImage& that) const {
|
||||||
const ArbitraryImage* that2 = dynamic_cast<const ArbitraryImage*>(&that);
|
const ArbitraryImage* that2 = dynamic_cast<const ArbitraryImage*>(&that);
|
||||||
return that2 && image.IsSameAs(that2->image);
|
return that2 && image.IsSameAs(that2->image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : SymbolToImage
|
// ----------------------------------------------------------------------------- : SymbolToImage
|
||||||
@@ -716,48 +716,48 @@ bool ImageValueToImage::operator == (const GeneratedImage& that) const {
|
|||||||
return that2 && filename == that2->filename
|
return that2 && filename == that2->filename
|
||||||
&& age == that2->age;
|
&& age == that2->age;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ExternalImage
|
// ----------------------------------------------------------------------------- : ExternalImage
|
||||||
|
|
||||||
Image ExternalImage::generate(const Options& opt) const {
|
Image ExternalImage::generate(const Options& opt) const {
|
||||||
wxFileName fname(filepath, wxPATH_UNIX);
|
wxFileName fname(filepath, wxPATH_UNIX);
|
||||||
String filePathString = fname.GetAbsolutePath();
|
String filePathString = fname.GetAbsolutePath();
|
||||||
|
|
||||||
// has a pre-existing .mse-set file been loaded?
|
// has a pre-existing .mse-set file been loaded?
|
||||||
if (opt.local_package->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", filePathString));
|
if (opt.local_package->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", filePathString));
|
||||||
|
|
||||||
// does the file pointed to by filepath exist?
|
// does the file pointed to by filepath exist?
|
||||||
if (!fname.FileExists()) throw ScriptError(_ERROR_1_("import not found", filePathString));
|
if (!fname.FileExists()) throw ScriptError(_ERROR_1_("import not found", filePathString));
|
||||||
|
|
||||||
String fileExt = fname.GetExt();
|
String fileExt = fname.GetExt();
|
||||||
wxBitmapType bitmapType;
|
wxBitmapType bitmapType;
|
||||||
if (fileExt == _("png")) bitmapType = wxBITMAP_TYPE_PNG;
|
if (fileExt == _("png")) bitmapType = wxBITMAP_TYPE_PNG;
|
||||||
else if (fileExt == _("jpg") || fileExt == _("jpeg")) bitmapType = wxBITMAP_TYPE_JPEG;
|
else if (fileExt == _("jpg") || fileExt == _("jpeg")) bitmapType = wxBITMAP_TYPE_JPEG;
|
||||||
else bitmapType = wxBITMAP_TYPE_BMP;
|
else bitmapType = wxBITMAP_TYPE_BMP;
|
||||||
|
|
||||||
// does the file exist in the package?
|
// does the file exist in the package?
|
||||||
String fileNameNoExtension = fname.GetName();
|
String fileNameNoExtension = fname.GetName();
|
||||||
if (!opt.local_package->existsIn(fileNameNoExtension)) {
|
if (!opt.local_package->existsIn(fileNameNoExtension)) {
|
||||||
auto outStream = opt.local_package->openOut(fileNameNoExtension);
|
auto outStream = opt.local_package->openOut(fileNameNoExtension);
|
||||||
wxFileInputStream inStream = wxFileInputStream(filepath.ToStdString());
|
wxFileInputStream inStream = wxFileInputStream(filepath.ToStdString());
|
||||||
if (!inStream.IsOk()) throw ScriptError(_ERROR_1_("can't create file stream", filePathString));
|
if (!inStream.IsOk()) throw ScriptError(_ERROR_1_("can't create file stream", filePathString));
|
||||||
outStream->Write(inStream);
|
outStream->Write(inStream);
|
||||||
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", filePathString));
|
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", filePathString));
|
||||||
outStream->Close();
|
outStream->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the package with the new image
|
// save the package with the new image
|
||||||
opt.local_package->save(false);
|
opt.local_package->save(false);
|
||||||
|
|
||||||
auto imageInputStream = opt.local_package->openIn(fileNameNoExtension);
|
auto imageInputStream = opt.local_package->openIn(fileNameNoExtension);
|
||||||
Image img(*imageInputStream.get(), bitmapType);
|
Image img(*imageInputStream.get(), bitmapType);
|
||||||
|
|
||||||
if (!img.IsOk()) throw ScriptError(_ERROR_1_("can't import image", filePathString));
|
if (!img.IsOk()) throw ScriptError(_ERROR_1_("can't import image", filePathString));
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalImage::operator == (const GeneratedImage& that) const {
|
bool ExternalImage::operator == (const GeneratedImage& that) const {
|
||||||
const ExternalImage* that2 = dynamic_cast<const ExternalImage*>(&that);
|
const ExternalImage* that2 = dynamic_cast<const ExternalImage*>(&that);
|
||||||
return that2 && that2->filepath == filepath;
|
return that2 && that2->filepath == filepath;
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-27
@@ -327,9 +327,9 @@ public:
|
|||||||
{}
|
{}
|
||||||
Image generate(const Options& opt) const override;
|
Image generate(const Options& opt) const override;
|
||||||
bool operator == (const GeneratedImage& that) const override;
|
bool operator == (const GeneratedImage& that) const override;
|
||||||
private:
|
private:
|
||||||
GeneratedImageP base_image;
|
GeneratedImageP base_image;
|
||||||
double horizontal_size, vertical_size;
|
double horizontal_size, vertical_size;
|
||||||
Color background_color;
|
Color background_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -395,18 +395,18 @@ public:
|
|||||||
bool operator == (const GeneratedImage& that) const override;
|
bool operator == (const GeneratedImage& that) const override;
|
||||||
private:
|
private:
|
||||||
String name;
|
String name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Arbitrary
|
// ----------------------------------------------------------------------------- : Arbitrary
|
||||||
|
|
||||||
class ArbitraryImage : public GeneratedImage {
|
class ArbitraryImage : public GeneratedImage {
|
||||||
public:
|
public:
|
||||||
inline ArbitraryImage(const Image image)
|
inline ArbitraryImage(const Image image)
|
||||||
: image(image)
|
: image(image)
|
||||||
{}
|
{}
|
||||||
Image generate(const Options& opt) const override;
|
Image generate(const Options& opt) const override;
|
||||||
bool operator == (const GeneratedImage& that) const override;
|
bool operator == (const GeneratedImage& that) const override;
|
||||||
private:
|
private:
|
||||||
Image image;
|
Image image;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -447,17 +447,17 @@ private:
|
|||||||
LocalFileName filename;
|
LocalFileName filename;
|
||||||
Age age; ///< Age the image was last updated
|
Age age; ///< Age the image was last updated
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ExternalImage
|
// ----------------------------------------------------------------------------- : ExternalImage
|
||||||
|
|
||||||
/// Load an image from the filesystem
|
/// Load an image from the filesystem
|
||||||
class ExternalImage : public GeneratedImage {
|
class ExternalImage : public GeneratedImage {
|
||||||
public:
|
public:
|
||||||
ExternalImage(const String& filepath) : filepath(filepath) {};
|
ExternalImage(const String& filepath) : filepath(filepath) {};
|
||||||
Image generate(const Options&) const override;
|
Image generate(const Options&) const override;
|
||||||
bool operator == (const GeneratedImage& that) const override;
|
bool operator == (const GeneratedImage& that) const override;
|
||||||
inline String toString() { return filepath; }
|
inline String toString() { return filepath; }
|
||||||
inline String toCode() const override { return _("<image>"); }
|
inline String toCode() const override { return _("<image>"); }
|
||||||
private:
|
private:
|
||||||
String filepath;
|
String filepath;
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -172,7 +172,7 @@ enum ImageCombine
|
|||||||
, COMBINE_GREATER_THAN_235
|
, COMBINE_GREATER_THAN_235
|
||||||
, COMBINE_GREATER_THAN_240
|
, COMBINE_GREATER_THAN_240
|
||||||
, COMBINE_GREATER_THAN_245
|
, COMBINE_GREATER_THAN_245
|
||||||
, COMBINE_GREATER_THAN_250
|
, COMBINE_GREATER_THAN_250
|
||||||
, COMBINE_SMALLER_THAN_5
|
, COMBINE_SMALLER_THAN_5
|
||||||
, COMBINE_SMALLER_THAN_10
|
, COMBINE_SMALLER_THAN_10
|
||||||
, COMBINE_SMALLER_THAN_15
|
, COMBINE_SMALLER_THAN_15
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <util/prec.hpp>
|
||||||
|
#include <data/game.hpp>
|
||||||
|
#include <gui/card_link_window.hpp>
|
||||||
|
#include <gui/control/select_card_list.hpp>
|
||||||
|
#include <util/window_id.hpp>
|
||||||
|
#include <data/action/set.hpp>
|
||||||
|
#include <wx/statline.h>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : ExportCardSelectionChoice
|
||||||
|
|
||||||
|
CardLinkWindow::CardLinkWindow(Window* parent, const SetP& set, const CardP& selected_card, bool sizer)
|
||||||
|
: wxDialog(parent, wxID_ANY, _TITLE_("link cards"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||||
|
, set(set), selected_card(selected_card)
|
||||||
|
{
|
||||||
|
// init controls
|
||||||
|
selected_relation = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
|
||||||
|
linked_relation = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
|
||||||
|
relation_type = new wxChoice(this, ID_CARD_LINK_TYPE, wxDefaultPosition, wxDefaultSize, 0, nullptr);
|
||||||
|
relation_type->Clear();
|
||||||
|
FOR_EACH(link, set->game->card_links) {
|
||||||
|
relation_type->Append(link);
|
||||||
|
}
|
||||||
|
relation_type->Append(_LABEL_("custom link"));
|
||||||
|
relation_type->SetSelection(0);
|
||||||
|
setRelationType();
|
||||||
|
list = new SelectCardList(this, wxID_ANY);
|
||||||
|
list->setSet(set);
|
||||||
|
list->selectNone();
|
||||||
|
sel_none = new wxButton(this, ID_SELECT_NONE, _BUTTON_("select none"));
|
||||||
|
// init sizers
|
||||||
|
if (sizer) {
|
||||||
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||||
|
s->Add(new wxStaticText(this, -1, _LABEL_("linked cards relation")), 0, wxALL, 8);
|
||||||
|
s->Add(relation_type, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||||
|
s->Add(new wxStaticText(this, -1, _(" ") + _LABEL_("selected card")), 0, wxALL, 4);
|
||||||
|
s->Add(selected_relation, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||||
|
s->Add(new wxStaticText(this, -1, _(" ") + _LABEL_("linked cards")), 0, wxALL, 4);
|
||||||
|
s->Add(linked_relation, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||||
|
s->Add(new wxStaticText(this, wxID_ANY, _LABEL_("select linked cards")), 0, wxALL & ~wxBOTTOM, 8);
|
||||||
|
s->Add(list, 1, wxEXPAND | wxALL, 8);
|
||||||
|
wxSizer* s2 = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
s2->Add(sel_none, 0, wxEXPAND | wxRIGHT, 8);
|
||||||
|
s2->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxEXPAND, 8);
|
||||||
|
s->Add(s2, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||||
|
s->SetSizeHints(this);
|
||||||
|
SetSizer(s);
|
||||||
|
SetSize(600,500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CardLinkWindow::isSelected(const CardP& card) const {
|
||||||
|
return list->isSelected(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardLinkWindow::getSelection(vector<CardP>& out) const {
|
||||||
|
list->getSelection(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardLinkWindow::setSelection(const vector<CardP>& cards) {
|
||||||
|
list->setSelection(cards);
|
||||||
|
}
|
||||||
|
void CardLinkWindow::setRelationType() {
|
||||||
|
int sel = relation_type->GetSelection();
|
||||||
|
if (sel == relation_type->GetCount() - 1) { // Custom type
|
||||||
|
selected_relation->ChangeValue(_LABEL_("custom link selected"));
|
||||||
|
selected_relation->Enable();
|
||||||
|
linked_relation->ChangeValue(_LABEL_("custom link linked"));
|
||||||
|
linked_relation->Enable();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String relation = relation_type->GetString(sel);
|
||||||
|
int delimiter_pos = relation.find("//");
|
||||||
|
selected_relation->ChangeValue(relation.substr(0, delimiter_pos).Trim().Trim(false));
|
||||||
|
selected_relation->Enable(false);
|
||||||
|
linked_relation->ChangeValue(delimiter_pos + 2 < relation.Length() ? relation.substr(delimiter_pos + 2).Trim().Trim(false) : _LABEL_("custom link undefined"));
|
||||||
|
linked_relation->Enable(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardLinkWindow::onSelectNone(wxCommandEvent&) {
|
||||||
|
list->selectNone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardLinkWindow::onRelationTypeChange(wxCommandEvent&) {
|
||||||
|
setRelationType();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardLinkWindow::onOk(wxCommandEvent&) {
|
||||||
|
// Perform the linking
|
||||||
|
// The selected_card is the one selected on the main cards tab
|
||||||
|
// The linked_cards are the ones selected in this dialogue window
|
||||||
|
vector<CardP> linked_cards;
|
||||||
|
getSelection(linked_cards);
|
||||||
|
set->actions.addAction(make_unique<LinkCardsAction>(*set, selected_card, linked_cards, selected_relation->GetValue(), linked_relation->GetValue()));
|
||||||
|
// Done
|
||||||
|
EndModal(wxID_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(CardLinkWindow, wxDialog)
|
||||||
|
EVT_BUTTON (ID_SELECT_NONE, CardLinkWindow::onSelectNone)
|
||||||
|
EVT_BUTTON (wxID_OK, CardLinkWindow::onOk)
|
||||||
|
EVT_CHOICE (ID_CARD_LINK_TYPE, CardLinkWindow::onRelationTypeChange)
|
||||||
|
END_EVENT_TABLE ()
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <util/prec.hpp>
|
||||||
|
|
||||||
|
DECLARE_POINTER_TYPE(Set);
|
||||||
|
DECLARE_POINTER_TYPE(Card);
|
||||||
|
DECLARE_POINTER_TYPE(ExportCardSelectionChoice);
|
||||||
|
class SelectCardList;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : CardLinkWindow
|
||||||
|
|
||||||
|
/// A window for selecting a subset of the cards from a set,
|
||||||
|
/** and selecting a link relation type.
|
||||||
|
/** this is used when linking cards
|
||||||
|
*/
|
||||||
|
class CardLinkWindow : public wxDialog {
|
||||||
|
public:
|
||||||
|
CardLinkWindow(Window* parent, const SetP& set, const CardP& selected_card, bool sizer=true);
|
||||||
|
|
||||||
|
/// Is the given card selected?
|
||||||
|
bool isSelected(const CardP& card) const;
|
||||||
|
/// Get a list of all selected cards
|
||||||
|
void getSelection(vector<CardP>& out) const;
|
||||||
|
/// Change which cards are selected
|
||||||
|
void setSelection(const vector<CardP>& cards);
|
||||||
|
/// Change the type of link relation
|
||||||
|
void setRelationType();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
|
wxChoice* relation_type;
|
||||||
|
wxTextCtrl* selected_relation, *linked_relation;
|
||||||
|
SelectCardList* list;
|
||||||
|
SetP set;
|
||||||
|
CardP selected_card;
|
||||||
|
wxButton* sel_none;
|
||||||
|
|
||||||
|
void onRelationTypeChange(wxCommandEvent&);
|
||||||
|
|
||||||
|
void onOk(wxCommandEvent&);
|
||||||
|
|
||||||
|
void onSelectNone(wxCommandEvent&);
|
||||||
|
};
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <gui/control/card_editor.hpp>
|
#include <gui/control/card_editor.hpp>
|
||||||
#include <gui/value/editor.hpp>
|
#include <gui/value/editor.hpp>
|
||||||
|
#include <gui/set/cards_panel.hpp>
|
||||||
#include <gui/util.hpp>
|
#include <gui/util.hpp>
|
||||||
#include <data/field.hpp>
|
#include <data/field.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
@@ -360,6 +361,16 @@ void DataEditor::onMotion(wxMouseEvent& ev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataEditor::onMouseEnter(wxMouseEvent& ev) {
|
||||||
|
ev.Skip();
|
||||||
|
if (GetId() == ID_CARD_LINK_EDITOR) {
|
||||||
|
CardsPanel* panel = dynamic_cast<CardsPanel*> (GetParent());
|
||||||
|
if (panel) {
|
||||||
|
panel->refreshCard(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DataEditor::onMouseLeave(wxMouseEvent& ev) {
|
void DataEditor::onMouseLeave(wxMouseEvent& ev) {
|
||||||
// on mouse leave for editor
|
// on mouse leave for editor
|
||||||
if (hovered_viewer) {
|
if (hovered_viewer) {
|
||||||
@@ -462,6 +473,13 @@ void DataEditor::onChar(wxKeyEvent& ev) {
|
|||||||
} else {
|
} else {
|
||||||
ev.Skip();
|
ev.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GetId() == ID_CARD_LINK_EDITOR) {
|
||||||
|
CardsPanel* panel = dynamic_cast<CardsPanel*> (GetParent());
|
||||||
|
if (panel) {
|
||||||
|
panel->refreshCard(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Menu events
|
// ----------------------------------------------------------------------------- : Menu events
|
||||||
@@ -503,6 +521,10 @@ void DataEditor::onFocus(wxFocusEvent& ev) {
|
|||||||
selectFirst();
|
selectFirst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CardsPanel* panel = dynamic_cast<CardsPanel*> (GetParent());
|
||||||
|
if (panel) {
|
||||||
|
panel->setFocusedEditor(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void DataEditor::onLoseFocus(wxFocusEvent& ev) {
|
void DataEditor::onLoseFocus(wxFocusEvent& ev) {
|
||||||
if (current_editor) {
|
if (current_editor) {
|
||||||
@@ -520,6 +542,7 @@ BEGIN_EVENT_TABLE(DataEditor, CardViewer)
|
|||||||
EVT_RIGHT_DOWN (DataEditor::onRightDown)
|
EVT_RIGHT_DOWN (DataEditor::onRightDown)
|
||||||
EVT_MOTION (DataEditor::onMotion)
|
EVT_MOTION (DataEditor::onMotion)
|
||||||
EVT_MOUSEWHEEL (DataEditor::onMouseWheel)
|
EVT_MOUSEWHEEL (DataEditor::onMouseWheel)
|
||||||
|
EVT_ENTER_WINDOW (DataEditor::onMouseEnter)
|
||||||
EVT_LEAVE_WINDOW (DataEditor::onMouseLeave)
|
EVT_LEAVE_WINDOW (DataEditor::onMouseLeave)
|
||||||
EVT_CONTEXT_MENU (DataEditor::onContextMenu)
|
EVT_CONTEXT_MENU (DataEditor::onContextMenu)
|
||||||
EVT_MENU (wxID_ANY, DataEditor::onMenu)
|
EVT_MENU (wxID_ANY, DataEditor::onMenu)
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ private:
|
|||||||
void onRightDown (wxMouseEvent&);
|
void onRightDown (wxMouseEvent&);
|
||||||
void onMotion (wxMouseEvent&);
|
void onMotion (wxMouseEvent&);
|
||||||
void onMouseWheel(wxMouseEvent&);
|
void onMouseWheel(wxMouseEvent&);
|
||||||
|
void onMouseEnter(wxMouseEvent&);
|
||||||
void onMouseLeave(wxMouseEvent&);
|
void onMouseLeave(wxMouseEvent&);
|
||||||
void onLoseCapture(wxMouseCaptureLostEvent&);
|
void onLoseCapture(wxMouseCaptureLostEvent&);
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,9 @@
|
|||||||
#include <gui/control/card_list.hpp>
|
#include <gui/control/card_list.hpp>
|
||||||
#include <gui/control/card_list_column_select.hpp>
|
#include <gui/control/card_list_column_select.hpp>
|
||||||
#include <gui/set/window.hpp> // for sorting all cardlists in a window
|
#include <gui/set/window.hpp> // for sorting all cardlists in a window
|
||||||
#include <gui/util.hpp>
|
#include <gui/card_link_window.hpp>
|
||||||
#include <gui/add_csv_window.hpp>
|
#include <gui/util.hpp>
|
||||||
|
#include <gui/add_csv_window.hpp>
|
||||||
#include <gui/add_json_window.hpp>
|
#include <gui/add_json_window.hpp>
|
||||||
#include <data/game.hpp>
|
#include <data/game.hpp>
|
||||||
#include <data/field.hpp>
|
#include <data/field.hpp>
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
#include <data/action/value.hpp>
|
#include <data/action/value.hpp>
|
||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
DECLARE_POINTER_TYPE(ChoiceValue);
|
DECLARE_POINTER_TYPE(ChoiceValue);
|
||||||
|
|
||||||
@@ -157,6 +159,31 @@ bool CardListBase::doCopy() {
|
|||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
bool CardListBase::doCopyCardAndLinkedCards() {
|
||||||
|
if (!canCopy()) return false;
|
||||||
|
vector<CardP> cards_selected;
|
||||||
|
getSelection(cards_selected);
|
||||||
|
if (cards_selected.size() < 1) return false;
|
||||||
|
if (!wxTheClipboard->Open()) return false;
|
||||||
|
vector<CardP> cards_to_copy;
|
||||||
|
unordered_set<CardP> cards_already_added;
|
||||||
|
FOR_EACH(card, cards_selected) {
|
||||||
|
if (cards_already_added.find(card) == cards_already_added.end()) {
|
||||||
|
cards_to_copy.push_back(card);
|
||||||
|
cards_already_added.insert(card);
|
||||||
|
}
|
||||||
|
vector<pair<CardP, String>> linked_cards = card->getLinkedCards(*set);
|
||||||
|
FOR_EACH(linked_card, linked_cards) {
|
||||||
|
if (cards_already_added.find(linked_card.first) == cards_already_added.end()) {
|
||||||
|
cards_to_copy.push_back(linked_card.first);
|
||||||
|
cards_already_added.insert(linked_card.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, cards_to_copy)); // ignore result
|
||||||
|
wxTheClipboard->Close();
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
bool CardListBase::doPaste() {
|
bool CardListBase::doPaste() {
|
||||||
// get data
|
// get data
|
||||||
if (!canPaste()) return false;
|
if (!canPaste()) return false;
|
||||||
@@ -182,7 +209,26 @@ bool CardListBase::doDelete() {
|
|||||||
set->actions.addAction(make_unique<AddCardAction>(REMOVE, *set, cards_to_delete));
|
set->actions.addAction(make_unique<AddCardAction>(REMOVE, *set, cards_to_delete));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------- : CardListBase : Card linking
|
||||||
|
|
||||||
|
bool CardListBase::canLink() const {
|
||||||
|
vector<CardP> selected_cards;
|
||||||
|
getSelection(selected_cards);
|
||||||
|
return selected_cards.size() == 1;
|
||||||
|
}
|
||||||
|
bool CardListBase::doLink() {
|
||||||
|
CardLinkWindow wnd(this, set, getCard());
|
||||||
|
if (wnd.ShowModal() == wxID_OK) {
|
||||||
|
// The actual linking is done in this window's onOk function
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool CardListBase::doUnlink(CardP unlinked_card) {
|
||||||
|
set->actions.addAction(make_unique<UnlinkCardsAction>(*set, getCard(), unlinked_card));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool CardListBase::doAddCSV() {
|
bool CardListBase::doAddCSV() {
|
||||||
AddCSVWindow wnd(this, set, true);
|
AddCSVWindow wnd(this, set, true);
|
||||||
if (wnd.ShowModal() == wxID_OK) {
|
if (wnd.ShowModal() == wxID_OK) {
|
||||||
@@ -190,8 +236,8 @@ bool CardListBase::doAddCSV() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardListBase::doAddJSON() {
|
bool CardListBase::doAddJSON() {
|
||||||
AddJSONWindow wnd(this, set, true);
|
AddJSONWindow wnd(this, set, true);
|
||||||
if (wnd.ShowModal() == wxID_OK) {
|
if (wnd.ShowModal() == wxID_OK) {
|
||||||
@@ -199,7 +245,7 @@ bool CardListBase::doAddJSON() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : CardListBase : Building the list
|
// ----------------------------------------------------------------------------- : CardListBase : Building the list
|
||||||
|
|
||||||
@@ -412,10 +458,12 @@ void CardListBase::onContextMenu(wxContextMenuEvent&) {
|
|||||||
wxMenu m;
|
wxMenu m;
|
||||||
add_menu_item_tr(&m, wxID_CUT, "cut", "cut_card");
|
add_menu_item_tr(&m, wxID_CUT, "cut", "cut_card");
|
||||||
add_menu_item_tr(&m, wxID_COPY, "copy", "copy_card");
|
add_menu_item_tr(&m, wxID_COPY, "copy", "copy_card");
|
||||||
|
add_menu_item_tr(&m, ID_CARD_AND_LINK_COPY, "card_copy", "copy card and links");
|
||||||
add_menu_item_tr(&m, wxID_PASTE, "paste", "paste_card");
|
add_menu_item_tr(&m, wxID_PASTE, "paste", "paste_card");
|
||||||
m.AppendSeparator();
|
m.AppendSeparator();
|
||||||
add_menu_item_tr(&m, ID_CARD_ADD, "card_add", "add card");
|
add_menu_item_tr(&m, ID_CARD_ADD, "card_add", "add card");
|
||||||
add_menu_item_tr(&m, ID_CARD_REMOVE, "card_del", "remove card");
|
add_menu_item_tr(&m, ID_CARD_REMOVE, "card_del", "remove card");
|
||||||
|
add_menu_item_tr(&m, ID_CARD_LINK, "card_link", "link card");
|
||||||
PopupMenu(&m);
|
PopupMenu(&m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ public:
|
|||||||
|
|
||||||
// --------------------------------------------------- : Selection
|
// --------------------------------------------------- : Selection
|
||||||
|
|
||||||
inline CardP getCard() const { return static_pointer_cast<Card>(selected_item); }
|
inline CardP getCard() const { return static_pointer_cast<Card>(selected_item); }
|
||||||
inline void setCard(const CardP& card) { selectItem(card, true, false); }
|
inline void setCard(const CardP& card, bool event = false) { selectItem(card, true, event); }
|
||||||
|
|
||||||
// --------------------------------------------------- : Clipboard
|
// --------------------------------------------------- : Clipboard
|
||||||
|
|
||||||
bool canCut() const override;
|
bool canCut() const override;
|
||||||
@@ -75,11 +75,18 @@ public:
|
|||||||
bool canDelete() const override;
|
bool canDelete() const override;
|
||||||
// Try to perform a clipboard operation, return success
|
// Try to perform a clipboard operation, return success
|
||||||
bool doCopy() override;
|
bool doCopy() override;
|
||||||
|
bool doCopyCardAndLinkedCards();
|
||||||
bool doPaste() override;
|
bool doPaste() override;
|
||||||
bool doDelete() override;
|
bool doDelete() override;
|
||||||
bool doAddCSV();
|
bool doAddCSV();
|
||||||
bool doAddJSON();
|
bool doAddJSON();
|
||||||
|
|
||||||
|
// --------------------------------------------------- : Card linking
|
||||||
|
|
||||||
|
bool canLink() const;
|
||||||
|
bool doLink();
|
||||||
|
bool doUnlink(CardP unlinked_card);
|
||||||
|
|
||||||
// --------------------------------------------------- : Set actions
|
// --------------------------------------------------- : Set actions
|
||||||
|
|
||||||
void onBeforeChangeSet() override;
|
void onBeforeChangeSet() override;
|
||||||
@@ -107,7 +114,7 @@ protected:
|
|||||||
|
|
||||||
/// Send an 'item selected' event for the currently selected item (selected_item)
|
/// Send an 'item selected' event for the currently selected item (selected_item)
|
||||||
void sendEvent() override { sendEvent(EVENT_CARD_SELECT); }
|
void sendEvent() override { sendEvent(EVENT_CARD_SELECT); }
|
||||||
void sendEvent(int type = EVENT_CARD_SELECT);
|
void sendEvent(int type);
|
||||||
/// Compare cards
|
/// Compare cards
|
||||||
bool compareItems(void* a, void* b) const override;
|
bool compareItems(void* a, void* b) const override;
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,13 @@
|
|||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <gui/control/card_viewer.hpp>
|
#include <gui/control/card_viewer.hpp>
|
||||||
|
#include <gui/control/image_card_list.hpp>
|
||||||
|
#include <gui/set/cards_panel.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/settings.hpp>
|
#include <data/settings.hpp>
|
||||||
#include <render/value/viewer.hpp>
|
#include <render/value/viewer.hpp>
|
||||||
#include <wx/dcbuffer.h>
|
#include <wx/dcbuffer.h>
|
||||||
|
#include <util/window_id.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Events
|
// ----------------------------------------------------------------------------- : Events
|
||||||
|
|
||||||
@@ -31,7 +34,11 @@ wxSize CardViewer::DoGetBestSize() const {
|
|||||||
if (set) {
|
if (set) {
|
||||||
if (!stylesheet) stylesheet = set->stylesheet;
|
if (!stylesheet) stylesheet = set->stylesheet;
|
||||||
StyleSheetSettings& ss = settings.stylesheetSettingsFor(*stylesheet);
|
StyleSheetSettings& ss = settings.stylesheetSettingsFor(*stylesheet);
|
||||||
wxSize size(int(stylesheet->card_width * (150.0 / stylesheet->card_dpi) * ss.card_zoom()), int(stylesheet->card_height * (150.0 / stylesheet->card_dpi) * ss.card_zoom()));
|
double dpi_factor = stylesheet->card_dpi <= 150.0 ? 1.0 : 150.0 / stylesheet->card_dpi;
|
||||||
|
double width = stylesheet->card_width * dpi_factor * ss.card_zoom();
|
||||||
|
double height = stylesheet->card_height * dpi_factor * ss.card_zoom();
|
||||||
|
double link_factor = GetId() == ID_CARD_LINK_VIEWER ? (height * 0.5 - 41.0) / height : GetId() == ID_CARD_LINK_EDITOR ? (height * 0.97 - 41.0) / height : 1.0; // Subtract 41 pixels for the link title
|
||||||
|
wxSize size(int(link_factor * width), int(link_factor * height));
|
||||||
if (is_sideways(deg_to_rad(ss.card_angle()))) swap(size.x, size.y);
|
if (is_sideways(deg_to_rad(ss.card_angle()))) swap(size.x, size.y);
|
||||||
return size + ws - cs;
|
return size + ws - cs;
|
||||||
}
|
}
|
||||||
@@ -104,6 +111,16 @@ void CardViewer::onPaint(wxPaintEvent&) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardViewer::onClick(wxMouseEvent& ev) {
|
||||||
|
ev.Skip(); // allow DataEditor::onLeftDown to process this event as well
|
||||||
|
if (GetId() == ID_CARD_LINK_VIEWER) {
|
||||||
|
CardsPanel* panel = dynamic_cast<CardsPanel*> (GetParent());
|
||||||
|
if (panel) {
|
||||||
|
panel->setCard(getCard(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CardViewer::drawViewer(RotatedDC& dc, ValueViewer& v) {
|
void CardViewer::drawViewer(RotatedDC& dc, ValueViewer& v) {
|
||||||
if (shouldDraw(v)) v.draw(dc);
|
if (shouldDraw(v)) v.draw(dc);
|
||||||
}
|
}
|
||||||
@@ -150,11 +167,15 @@ Rotation CardViewer::getRotation() const {
|
|||||||
StyleSheetSettings& ss = settings.stylesheetSettingsFor(*stylesheet);
|
StyleSheetSettings& ss = settings.stylesheetSettingsFor(*stylesheet);
|
||||||
int dx = CanScroll(wxHORIZONTAL) ? GetScrollPos(wxHORIZONTAL) : 0;
|
int dx = CanScroll(wxHORIZONTAL) ? GetScrollPos(wxHORIZONTAL) : 0;
|
||||||
int dy = CanScroll(wxVERTICAL) ? GetScrollPos(wxVERTICAL) : 0;
|
int dy = CanScroll(wxVERTICAL) ? GetScrollPos(wxVERTICAL) : 0;
|
||||||
return Rotation(deg_to_rad(ss.card_angle()), stylesheet->getCardRect().move(-dx,-dy,0,0), (150.0 / stylesheet->card_dpi) * ss.card_zoom(), 1.0, ROTATION_ATTACH_TOP_LEFT);
|
double dpi_factor = stylesheet->card_dpi <= 150.0 ? 1.0 : 150.0 / stylesheet->card_dpi;
|
||||||
|
double height = stylesheet->card_height * dpi_factor * ss.card_zoom();
|
||||||
|
double link_factor = GetId() == ID_CARD_LINK_VIEWER ? (height * 0.5 - 41.0) / height : GetId() == ID_CARD_LINK_EDITOR ? (height * 0.97 - 41.0) / height : 1.0; // Subtract 41 pixels for the link title
|
||||||
|
return Rotation(deg_to_rad(ss.card_angle()), stylesheet->getCardRect().move(-dx,-dy,0,0), link_factor * dpi_factor * ss.card_zoom(), 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Event table
|
// ----------------------------------------------------------------------------- : Event table
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(CardViewer, wxControl)
|
BEGIN_EVENT_TABLE(CardViewer, wxControl)
|
||||||
EVT_PAINT(CardViewer::onPaint)
|
EVT_PAINT(CardViewer::onPaint)
|
||||||
|
EVT_LEFT_DOWN(CardViewer::onClick)
|
||||||
END_EVENT_TABLE ()
|
END_EVENT_TABLE ()
|
||||||
|
|||||||
@@ -53,9 +53,11 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
void onPaint(wxPaintEvent&);
|
void onPaint(wxPaintEvent&);
|
||||||
|
|
||||||
|
void onClick(wxMouseEvent&);
|
||||||
|
|
||||||
Bitmap buffer; ///< Off-screen buffer we draw to
|
Bitmap buffer; ///< Off-screen buffer we draw to
|
||||||
bool up_to_date; ///< Is the buffer up to date?
|
bool up_to_date; ///< Is the buffer up to date?
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ void ItemList::selectItem(const VoidP& item, bool focus, bool event) {
|
|||||||
focusNone();
|
focusNone();
|
||||||
}
|
}
|
||||||
selected_item = item;
|
selected_item = item;
|
||||||
if (event) sendEvent();
|
if (event) sendEvent(); // sending an event will trigger a UI update
|
||||||
findSelectedItemPos();
|
findSelectedItemPos();
|
||||||
if (focus) focusSelectedItem();
|
if (focus) focusSelectedItem();
|
||||||
}
|
}
|
||||||
@@ -111,6 +111,14 @@ void ItemList::findSelectedItemPos() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
long ItemList::findGivenItemPos(const VoidP& item) {
|
||||||
|
long count = GetItemCount();
|
||||||
|
for (long pos = 0; pos < count; ++pos) {
|
||||||
|
if (getItem(pos) == item) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void ItemList::focusSelectedItem(bool force_focus) {
|
void ItemList::focusSelectedItem(bool force_focus) {
|
||||||
if (GetItemCount() > 0) {
|
if (GetItemCount() > 0) {
|
||||||
if (selected_item_pos == -1 || (size_t)selected_item_pos > sorted_list.size()) {
|
if (selected_item_pos == -1 || (size_t)selected_item_pos > sorted_list.size()) {
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ public:
|
|||||||
void selectFirst();
|
void selectFirst();
|
||||||
/// Select all items
|
/// Select all items
|
||||||
void doSelectAll();
|
void doSelectAll();
|
||||||
|
/// Find the position for a given item
|
||||||
|
long findGivenItemPos(const VoidP& item);
|
||||||
|
|
||||||
// --------------------------------------------------- : Clipboard
|
// --------------------------------------------------- : Clipboard
|
||||||
|
|
||||||
virtual bool canCut() const { return canCopy() && canDelete(); }
|
virtual bool canCut() const { return canCopy() && canDelete(); }
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ protected:
|
|||||||
virtual void onHide() {}
|
virtual void onHide() {}
|
||||||
|
|
||||||
inline bool isRoot() { return parent_menu == nullptr; }
|
inline bool isRoot() { return parent_menu == nullptr; }
|
||||||
|
|
||||||
/// Should the list of choices be displayed as a slider (if all choices are numbers)
|
/// Should the list of choices be displayed as a slider (if all choices are numbers)
|
||||||
bool is_slider = false;
|
bool is_slider = false;
|
||||||
|
|
||||||
// --------------------------------------------------- : Selection
|
// --------------------------------------------------- : Selection
|
||||||
static const size_t NO_SELECTION = (size_t)-1;
|
static const size_t NO_SELECTION = (size_t)-1;
|
||||||
@@ -82,12 +82,12 @@ protected:
|
|||||||
|
|
||||||
static const int marginW = 0;
|
static const int marginW = 0;
|
||||||
static const int marginH = 0;
|
static const int marginH = 0;
|
||||||
|
|
||||||
static bool slider_loaded;
|
static bool slider_loaded;
|
||||||
static wxBitmap slider_left;
|
static wxBitmap slider_left;
|
||||||
static wxBitmap slider_right;
|
static wxBitmap slider_right;
|
||||||
static wxBitmap slider_center;
|
static wxBitmap slider_center;
|
||||||
static wxBitmap slider_tick;
|
static wxBitmap slider_tick;
|
||||||
|
|
||||||
// may be changed by derived class
|
// may be changed by derived class
|
||||||
int text_offset; ///< Vertical distance between top of item and text
|
int text_offset; ///< Vertical distance between top of item and text
|
||||||
|
|||||||
+152
-85
@@ -13,15 +13,18 @@
|
|||||||
#include <util/rotation.hpp>
|
#include <util/rotation.hpp>
|
||||||
#include <gfx/gfx.hpp>
|
#include <gfx/gfx.hpp>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/dcbuffer.h>
|
#include <wx/dcbuffer.h>
|
||||||
|
|
||||||
|
map<String, String> ImageSliceWindow::previously_used_settings_path;
|
||||||
|
map<pair<String, String>, pair<wxRect, int>> ImageSliceWindow::previously_used_settings_value;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImageSlice
|
// ----------------------------------------------------------------------------- : ImageSlice
|
||||||
|
|
||||||
ImageSlice::ImageSlice(const Image& source, const wxSize& target_size)
|
ImageSlice::ImageSlice(const Image& source, const String& source_path, const String& card_name, const wxSize& target_size)
|
||||||
: source(source), target_size(target_size)
|
: source(source), source_path(source_path), card_name(card_name), target_size(target_size)
|
||||||
, selection(0, 0, source.GetWidth(), source.GetHeight())
|
, selection(0, 0, source.GetWidth(), source.GetHeight())
|
||||||
, allow_outside(false), aspect_fixed(true)
|
, allow_outside(false), aspect_fixed(true)
|
||||||
, sharpen(false), sharpen_amount(25)
|
, sharpen(false), sharpen_amount(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ImageSlice::constrain(PreferedProperty prefer) {
|
void ImageSlice::constrain(PreferedProperty prefer) {
|
||||||
@@ -51,24 +54,24 @@ void ImageSlice::constrain(PreferedProperty prefer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageSlice::centerSelection() {
|
void ImageSlice::centerSelection() {
|
||||||
centerSelectionHorizontally();
|
centerSelectionHorizontally();
|
||||||
centerSelectionVertically();
|
centerSelectionVertically();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageSlice::centerSelectionHorizontally() {
|
void ImageSlice::centerSelectionHorizontally() {
|
||||||
if (selection.GetWidth() < source.GetWidth()) {
|
if (selection.GetWidth() < source.GetWidth()) {
|
||||||
selection.x = ((source.GetWidth() - selection.GetWidth()) / 2);
|
selection.x = ((source.GetWidth() - selection.GetWidth()) / 2);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ImageSlice::centerSelectionVertically() {
|
|
||||||
if (selection.GetHeight() < source.GetHeight()) {
|
|
||||||
selection.y = ((source.GetHeight() - selection.GetHeight()) / 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image ImageSlice::getSlice(double scale) const {
|
void ImageSlice::centerSelectionVertically() {
|
||||||
|
if (selection.GetHeight() < source.GetHeight()) {
|
||||||
|
selection.y = ((source.GetHeight() - selection.GetHeight()) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image ImageSlice::getSlice(double scale) const {
|
||||||
wxSize scaled_target_size = target_size * scale;
|
wxSize scaled_target_size = target_size * scale;
|
||||||
if (selection.width == scaled_target_size.GetWidth() && selection.height == scaled_target_size.GetHeight() && selection.x == 0 && selection.y == 0) {
|
if (selection.width == scaled_target_size.GetWidth() && selection.height == scaled_target_size.GetHeight() && selection.x == 0 && selection.y == 0) {
|
||||||
// exactly the right size
|
// exactly the right size
|
||||||
@@ -93,20 +96,31 @@ DEFINE_EVENT_TYPE(EVENT_SLICE_CHANGED);
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImageSliceWindow
|
// ----------------------------------------------------------------------------- : ImageSliceWindow
|
||||||
|
|
||||||
ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wxSize& target_size, const AlphaMask& mask)
|
ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const String& filename, const String& cardname, const wxSize& target_size, const AlphaMask& mask)
|
||||||
: wxDialog(parent,wxID_ANY,_TITLE_("slice image"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
|
: wxDialog(parent,wxID_ANY,_TITLE_("slice image"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
|
||||||
, slice(source, target_size)
|
, slice(source, filename, cardname, target_size)
|
||||||
, initialized(false)
|
, initialized(false)
|
||||||
{
|
{
|
||||||
// init slice
|
// init slice
|
||||||
slice.constrain();
|
pair<String, String> settings_entry = { filename, cardname };
|
||||||
slice.centerSelection();
|
if (previously_used_settings_value.find(settings_entry) != previously_used_settings_value.end()) {
|
||||||
|
//slice.allow_outside = true; this currrently crashes
|
||||||
|
slice.aspect_fixed = false;
|
||||||
|
slice.sharpen = true;
|
||||||
|
slice.sharpen_amount = previously_used_settings_value[settings_entry].second;
|
||||||
|
slice.selection = previously_used_settings_value[settings_entry].first;
|
||||||
|
slice.constrain();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
slice.constrain();
|
||||||
|
slice.centerSelection();
|
||||||
|
}
|
||||||
|
|
||||||
// init controls
|
// init controls
|
||||||
const wxPoint defPos = wxDefaultPosition;
|
const wxPoint defPos = wxDefaultPosition;
|
||||||
const wxSize spinSize(80,-1);
|
const wxSize spinSize(80,-1);
|
||||||
selector = new ImageSliceSelector(this, ID_SELECTOR, slice);
|
selector = new ImageSliceSelector(this, ID_SELECTOR, slice);
|
||||||
preview = new ImageSlicePreview (this, ID_PREVIEW, slice, mask);
|
preview = new ImageSlicePreview (this, ID_PREVIEW, slice, mask, 0);
|
||||||
|
|
||||||
String sizes[] = { _LABEL_("original size")
|
String sizes[] = { _LABEL_("original size")
|
||||||
, _LABEL_("size to fit")
|
, _LABEL_("size to fit")
|
||||||
@@ -135,7 +149,14 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wx
|
|||||||
sharpen_amount = new wxSlider(this, ID_SHARPEN_AMOUNT, 0, 0, 100);
|
sharpen_amount = new wxSlider(this, ID_SHARPEN_AMOUNT, 0, 0, 100);
|
||||||
// allowOutside= new CheckBox(&this, idSliceAllowOutside, _("Allow selection outside source"))
|
// allowOutside= new CheckBox(&this, idSliceAllowOutside, _("Allow selection outside source"))
|
||||||
// bgColor = new ColorSelector(&this, wxID_ANY)
|
// bgColor = new ColorSelector(&this, wxID_ANY)
|
||||||
|
|
||||||
|
String grids[] = { _LABEL_("none")
|
||||||
|
, _LABEL_("grid halves")
|
||||||
|
, _LABEL_("grid thirds")
|
||||||
|
, _LABEL_("grid fourths")
|
||||||
|
, _LABEL_("grid fifths") };
|
||||||
|
grid = new wxRadioBox(this, ID_GRID, _LABEL_("grid"), defPos, wxDefaultSize, 5, grids, 1);
|
||||||
|
|
||||||
// init sizers
|
// init sizers
|
||||||
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||||
// top row: image editors
|
// top row: image editors
|
||||||
@@ -164,22 +185,22 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wx
|
|||||||
s7->Add(width, 0, wxEXPAND);
|
s7->Add(width, 0, wxEXPAND);
|
||||||
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection height")), 0, wxALIGN_CENTER_VERTICAL);
|
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection height")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
s7->Add(height, 0, wxEXPAND);
|
s7->Add(height, 0, wxEXPAND);
|
||||||
|
|
||||||
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection center")), 0, wxALIGN_CENTER_VERTICAL);
|
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection center")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
wxBoxSizer* s7A = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* s7A = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxBitmapButton* center_vertically_button = new wxBitmapButton(this, ID_SELECTION_CENTER_VERTICALLY, wxBitmap(load_resource_image(_("shape_align_middle"))));
|
wxBitmapButton* center_vertically_button = new wxBitmapButton(this, ID_SELECTION_CENTER_VERTICALLY, wxBitmap(load_resource_image(_("shape_align_middle"))));
|
||||||
center_vertically_button->SetToolTip(_LABEL_("selection center vertically"));
|
center_vertically_button->SetToolTip(_LABEL_("selection center vertically"));
|
||||||
s7A->Add(center_vertically_button);
|
s7A->Add(center_vertically_button);
|
||||||
s7A->AddStretchSpacer();
|
s7A->AddStretchSpacer();
|
||||||
|
|
||||||
wxBitmapButton* center_horizontally_button = new wxBitmapButton(this, ID_SELECTION_CENTER_HORIZONTALLY, wxBitmap(load_resource_image(_("shape_align_center"))));
|
wxBitmapButton* center_horizontally_button = new wxBitmapButton(this, ID_SELECTION_CENTER_HORIZONTALLY, wxBitmap(load_resource_image(_("shape_align_center"))));
|
||||||
center_horizontally_button->SetToolTip(_LABEL_("selection center horizontally"));
|
center_horizontally_button->SetToolTip(_LABEL_("selection center horizontally"));
|
||||||
s7A->Add(center_horizontally_button);
|
s7A->Add(center_horizontally_button);
|
||||||
s7A->AddStretchSpacer();
|
s7A->AddStretchSpacer();
|
||||||
|
|
||||||
wxBitmapButton* center_button = new wxBitmapButton(this, ID_SELECTION_CENTER, wxBitmap(load_resource_image(_("shape_align_both"))));
|
wxBitmapButton* center_button = new wxBitmapButton(this, ID_SELECTION_CENTER, wxBitmap(load_resource_image(_("shape_align_both"))));
|
||||||
center_button->SetToolTip(_LABEL_("selection center both"));
|
center_button->SetToolTip(_LABEL_("selection center both"));
|
||||||
s7A->Add(center_button);
|
s7A->Add(center_button);
|
||||||
s7->Add(s7A, 1, wxEXPAND, 0);
|
s7->Add(s7A, 1, wxEXPAND, 0);
|
||||||
s6->Add(s7, 1, wxEXPAND | wxALL, 4);
|
s6->Add(s7, 1, wxEXPAND | wxALL, 4);
|
||||||
s5->Add(s6, 0, wxEXPAND | wxALL, 4);
|
s5->Add(s6, 0, wxEXPAND | wxALL, 4);
|
||||||
@@ -206,6 +227,8 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wx
|
|||||||
sB->Add(sharpen_amount, 0, wxEXPAND | wxALL, 4);
|
sB->Add(sharpen_amount, 0, wxEXPAND | wxALL, 4);
|
||||||
s5->Add(sB, 0, wxEXPAND | wxALL, 4);
|
s5->Add(sB, 0, wxEXPAND | wxALL, 4);
|
||||||
s5->AddStretchSpacer(1);
|
s5->AddStretchSpacer(1);
|
||||||
|
s5->Add(grid, 0, wxEXPAND | wxALL, 4);
|
||||||
|
s5->AddStretchSpacer(1);
|
||||||
s->Add(s5, 0, wxEXPAND);
|
s->Add(s5, 0, wxEXPAND);
|
||||||
s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 8);
|
s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 8);
|
||||||
s->SetSizeHints(this);
|
s->SetSizeHints(this);
|
||||||
@@ -219,8 +242,11 @@ void ImageSliceWindow::onOk(wxCommandEvent&) {
|
|||||||
EndModal(wxID_OK);
|
EndModal(wxID_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image ImageSliceWindow::getImage(double scale) const {
|
Image ImageSliceWindow::getImage(double scale) const {
|
||||||
return slice.getSlice(scale);
|
Image img = slice.getSlice(scale);
|
||||||
|
previously_used_settings_path[slice.card_name] = slice.source_path;
|
||||||
|
previously_used_settings_value[{ slice.source_path, slice.card_name }] = { slice.selection, slice.sharpen_amount };
|
||||||
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImageSliceWindow : Controls
|
// ----------------------------------------------------------------------------- : ImageSliceWindow : Controls
|
||||||
@@ -249,7 +275,13 @@ void ImageSliceWindow::onChangeSize(wxCommandEvent&) {
|
|||||||
slice.aspect_fixed = false;
|
slice.aspect_fixed = false;
|
||||||
onUpdateFromControl();
|
onUpdateFromControl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageSliceWindow::onChangeGrid(wxCommandEvent&) {
|
||||||
|
if (!initialized) return;
|
||||||
|
preview->grid = grid->GetSelection();
|
||||||
|
preview->update();
|
||||||
|
}
|
||||||
|
|
||||||
void ImageSliceWindow::onChangeLeft(wxCommandEvent&) {
|
void ImageSliceWindow::onChangeLeft(wxCommandEvent&) {
|
||||||
if (!initialized) return;
|
if (!initialized) return;
|
||||||
@@ -322,16 +354,16 @@ void ImageSliceWindow::onUpdateFromControl(PreferedProperty prefer) {
|
|||||||
updateControls();
|
updateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageSliceWindow::onSelectionCenter(wxCommandEvent& ev) {
|
void ImageSliceWindow::onSelectionCenter(wxCommandEvent& ev) {
|
||||||
switch (ev.GetId()) {
|
switch (ev.GetId()) {
|
||||||
case ID_SELECTION_CENTER:
|
case ID_SELECTION_CENTER:
|
||||||
slice.centerSelection();
|
slice.centerSelection();
|
||||||
break;
|
break;
|
||||||
case ID_SELECTION_CENTER_HORIZONTALLY:
|
case ID_SELECTION_CENTER_HORIZONTALLY:
|
||||||
slice.centerSelectionHorizontally();
|
slice.centerSelectionHorizontally();
|
||||||
break;
|
break;
|
||||||
case ID_SELECTION_CENTER_VERTICALLY:
|
case ID_SELECTION_CENTER_VERTICALLY:
|
||||||
slice.centerSelectionVertically();
|
slice.centerSelectionVertically();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,22 +416,23 @@ void ImageSliceWindow::updateControls() {
|
|||||||
// ----------------------------------------------------------------------------- : ImageSliceWindow : Event table
|
// ----------------------------------------------------------------------------- : ImageSliceWindow : Event table
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(ImageSliceWindow, wxDialog)
|
BEGIN_EVENT_TABLE(ImageSliceWindow, wxDialog)
|
||||||
EVT_BUTTON (wxID_OK, ImageSliceWindow::onOk)
|
EVT_BUTTON (wxID_OK, ImageSliceWindow::onOk)
|
||||||
EVT_RADIOBOX (ID_SIZE, ImageSliceWindow::onChangeSize)
|
EVT_RADIOBOX (ID_SIZE, ImageSliceWindow::onChangeSize)
|
||||||
EVT_TEXT (ID_LEFT, ImageSliceWindow::onChangeLeft)
|
EVT_RADIOBOX (ID_GRID, ImageSliceWindow::onChangeGrid)
|
||||||
EVT_TEXT (ID_TOP, ImageSliceWindow::onChangeTop)
|
EVT_TEXT (ID_LEFT, ImageSliceWindow::onChangeLeft)
|
||||||
EVT_TEXT (ID_WIDTH, ImageSliceWindow::onChangeWidth)
|
EVT_TEXT (ID_TOP, ImageSliceWindow::onChangeTop)
|
||||||
EVT_TEXT (ID_HEIGHT, ImageSliceWindow::onChangeHeight)
|
EVT_TEXT (ID_WIDTH, ImageSliceWindow::onChangeWidth)
|
||||||
EVT_BUTTON (ID_SELECTION_CENTER, ImageSliceWindow::onSelectionCenter)
|
EVT_TEXT (ID_HEIGHT, ImageSliceWindow::onChangeHeight)
|
||||||
EVT_BUTTON(ID_SELECTION_CENTER_HORIZONTALLY, ImageSliceWindow::onSelectionCenter)
|
EVT_BUTTON (ID_SELECTION_CENTER, ImageSliceWindow::onSelectionCenter)
|
||||||
EVT_BUTTON(ID_SELECTION_CENTER_VERTICALLY, ImageSliceWindow::onSelectionCenter)
|
EVT_BUTTON (ID_SELECTION_CENTER_HORIZONTALLY, ImageSliceWindow::onSelectionCenter)
|
||||||
EVT_CHECKBOX (ID_FIX_ASPECT, ImageSliceWindow::onChangeFixAspect)
|
EVT_BUTTON (ID_SELECTION_CENTER_VERTICALLY, ImageSliceWindow::onSelectionCenter)
|
||||||
EVT_SPINCTRL (ID_ZOOM, ImageSliceWindow::onChangeZoom)
|
EVT_CHECKBOX (ID_FIX_ASPECT, ImageSliceWindow::onChangeFixAspect)
|
||||||
EVT_SPINCTRL (ID_ZOOM_X, ImageSliceWindow::onChangeZoomX)
|
EVT_SPINCTRL (ID_ZOOM, ImageSliceWindow::onChangeZoom)
|
||||||
EVT_SPINCTRL (ID_ZOOM_Y, ImageSliceWindow::onChangeZoomY)
|
EVT_SPINCTRL (ID_ZOOM_X, ImageSliceWindow::onChangeZoomX)
|
||||||
EVT_CHECKBOX (ID_SHARPEN, ImageSliceWindow::onChangeSharpen)
|
EVT_SPINCTRL (ID_ZOOM_Y, ImageSliceWindow::onChangeZoomY)
|
||||||
EVT_COMMAND_SCROLL (ID_SHARPEN_AMOUNT, ImageSliceWindow::onChangeSharpenAmount)
|
EVT_CHECKBOX (ID_SHARPEN, ImageSliceWindow::onChangeSharpen)
|
||||||
EVT_SLICE_CHANGED (wxID_ANY, ImageSliceWindow::onSliceChange)
|
EVT_COMMAND_SCROLL (ID_SHARPEN_AMOUNT, ImageSliceWindow::onChangeSharpenAmount)
|
||||||
|
EVT_SLICE_CHANGED (wxID_ANY, ImageSliceWindow::onSliceChange)
|
||||||
// EVT_SIZE ( ImageSliceWindow::onSize)
|
// EVT_SIZE ( ImageSliceWindow::onSize)
|
||||||
END_EVENT_TABLE ()
|
END_EVENT_TABLE ()
|
||||||
|
|
||||||
@@ -409,10 +442,11 @@ END_EVENT_TABLE ()
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImageSlicePreview
|
// ----------------------------------------------------------------------------- : ImageSlicePreview
|
||||||
|
|
||||||
ImageSlicePreview::ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask)
|
ImageSlicePreview::ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask, const int grid)
|
||||||
: wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME)
|
: wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME)
|
||||||
, slice(slice)
|
, slice(slice)
|
||||||
, mask(mask)
|
, mask(mask)
|
||||||
|
, grid(grid)
|
||||||
, mouse_down(false)
|
, mouse_down(false)
|
||||||
{
|
{
|
||||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||||
@@ -421,22 +455,22 @@ ImageSlicePreview::ImageSlicePreview(Window* parent, int id, ImageSlice& slice,
|
|||||||
void ImageSlicePreview::update() {
|
void ImageSlicePreview::update() {
|
||||||
bitmap = wxNullBitmap;
|
bitmap = wxNullBitmap;
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize ImageSlicePreview::getBestSliceSize() const {
|
wxSize ImageSlicePreview::getBestSliceSize() const {
|
||||||
float target_ratio = ((float)slice.target_size.GetWidth()) / ((float)slice.target_size.GetHeight());
|
float target_ratio = ((float)slice.target_size.GetWidth()) / ((float)slice.target_size.GetHeight());
|
||||||
if (target_ratio > 1.0) {
|
if (target_ratio > 1.0) {
|
||||||
return wxSize(500, 500 / target_ratio);
|
return wxSize(500, 500 / target_ratio);
|
||||||
} else {
|
} else {
|
||||||
return wxSize(500 * target_ratio, 500);
|
return wxSize(500 * target_ratio, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize ImageSlicePreview::DoGetBestSize() const {
|
wxSize ImageSlicePreview::DoGetBestSize() const {
|
||||||
// We know the client size we want, calculate the size that goes with that
|
// We know the client size we want, calculate the size that goes with that
|
||||||
// This helps with applying margins and other spacing necessities.
|
// This helps with applying margins and other spacing necessities.
|
||||||
wxSize ws = GetSize(), cs = GetClientSize();
|
wxSize ws = GetSize(), cs = GetClientSize();
|
||||||
|
|
||||||
return getBestSliceSize() + ws - cs;
|
return getBestSliceSize() + ws - cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,14 +495,47 @@ void ImageSlicePreview::draw(DC& dc) {
|
|||||||
mdc.SelectObject(wxNullBitmap);
|
mdc.SelectObject(wxNullBitmap);
|
||||||
} else {
|
} else {
|
||||||
bitmap = Bitmap(image);
|
bitmap = Bitmap(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rescale the bitmap based on the available size.
|
// Rescale the bitmap based on the available size.
|
||||||
auto available_size = getBestSliceSize();
|
auto available_size = getBestSliceSize();
|
||||||
bitmap = wxBitmap(bitmap.ConvertToImage().Scale(available_size.GetWidth(), available_size.GetHeight()));
|
bitmap = wxBitmap(bitmap.ConvertToImage().Scale(available_size.GetWidth(), available_size.GetHeight()));
|
||||||
}
|
}
|
||||||
if (bitmap.Ok()) {
|
if (bitmap.Ok()) {
|
||||||
dc.DrawBitmap(bitmap, 0, 0);
|
dc.DrawBitmap(bitmap, 0, 0);
|
||||||
|
if (grid == 1) {
|
||||||
|
wxSize size = dc.GetSize();
|
||||||
|
dc.SetPen(*wxRED_PEN);
|
||||||
|
dc.DrawLine(size.x * 1 / 2, 0, size.x * 1 / 2, size.y);
|
||||||
|
dc.DrawLine(0, size.y * 1 / 2, size.x, size.y * 1 / 2);
|
||||||
|
} else if (grid == 2) {
|
||||||
|
wxSize size = dc.GetSize();
|
||||||
|
dc.SetPen(*wxRED_PEN);
|
||||||
|
dc.DrawLine(size.x * 1 / 3, 0, size.x * 1 / 3, size.y);
|
||||||
|
dc.DrawLine(size.x * 2 / 3, 0, size.x * 2 / 3, size.y);
|
||||||
|
dc.DrawLine(0, size.y * 1 / 3, size.x, size.y * 1 / 3);
|
||||||
|
dc.DrawLine(0, size.y * 2 / 3, size.x, size.y * 2 / 3);
|
||||||
|
} else if (grid == 3) {
|
||||||
|
wxSize size = dc.GetSize();
|
||||||
|
dc.SetPen(*wxRED_PEN);
|
||||||
|
dc.DrawLine(size.x * 1 / 4, 0, size.x * 1 / 4, size.y);
|
||||||
|
dc.DrawLine(size.x * 2 / 4, 0, size.x * 2 / 4, size.y);
|
||||||
|
dc.DrawLine(size.x * 3 / 4, 0, size.x * 3 / 4, size.y);
|
||||||
|
dc.DrawLine(0, size.y * 1 / 4, size.x, size.y * 1 / 4);
|
||||||
|
dc.DrawLine(0, size.y * 2 / 4, size.x, size.y * 2 / 4);
|
||||||
|
dc.DrawLine(0, size.y * 3 / 4, size.x, size.y * 3 / 4);
|
||||||
|
} else if (grid == 4) {
|
||||||
|
wxSize size = dc.GetSize();
|
||||||
|
dc.SetPen(*wxRED_PEN);
|
||||||
|
dc.DrawLine(size.x * 1 / 5, 0, size.x * 1 / 5, size.y);
|
||||||
|
dc.DrawLine(size.x * 2 / 5, 0, size.x * 2 / 5, size.y);
|
||||||
|
dc.DrawLine(size.x * 3 / 5, 0, size.x * 3 / 5, size.y);
|
||||||
|
dc.DrawLine(size.x * 4 / 5, 0, size.x * 4 / 5, size.y);
|
||||||
|
dc.DrawLine(0, size.y * 1 / 5, size.x, size.y * 1 / 5);
|
||||||
|
dc.DrawLine(0, size.y * 2 / 5, size.x, size.y * 2 / 5);
|
||||||
|
dc.DrawLine(0, size.y * 3 / 5, size.x, size.y * 3 / 5);
|
||||||
|
dc.DrawLine(0, size.y * 4 / 5, size.x, size.y * 4 / 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,9 +586,9 @@ ImageSliceSelector::ImageSliceSelector(Window* parent, int id, ImageSlice& slice
|
|||||||
: wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME)
|
: wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME)
|
||||||
, slice(slice)
|
, slice(slice)
|
||||||
, mouse_down(false)
|
, mouse_down(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
float target_ratio = ((float) slice.source.GetWidth()) / ((float) slice.source.GetHeight());
|
float target_ratio = ((float) slice.source.GetWidth()) / ((float) slice.source.GetHeight());
|
||||||
if (target_ratio > 1.0) {
|
if (target_ratio > 1.0) {
|
||||||
SetMinSize(wxSize(500, 500 / target_ratio));
|
SetMinSize(wxSize(500, 500 / target_ratio));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,23 +28,26 @@ enum PreferedProperty
|
|||||||
/// A slice of an image, i.e. a selected rectangle
|
/// A slice of an image, i.e. a selected rectangle
|
||||||
class ImageSlice {
|
class ImageSlice {
|
||||||
public:
|
public:
|
||||||
ImageSlice(const Image& source, const wxSize& target_size);
|
ImageSlice(const Image& source, const String& source_path, const String& card_name, const wxSize& target_size);
|
||||||
|
|
||||||
Image source; ///< The source image
|
Image source; ///< The source image
|
||||||
wxSize target_size; ///< Size of the target image
|
String source_path; ///< The filename of the source image (only used to find previously used settings)
|
||||||
Color background; ///< Color for areas outside the source image
|
String card_name; ///< The identification of the card we're on (only used to find previously used settings)
|
||||||
wxRect selection; ///< Area to slect from source
|
wxSize target_size; ///< Size of the target image
|
||||||
bool allow_outside;
|
wxRect selection; ///< Area to slice from source
|
||||||
bool aspect_fixed; ///< Aspect ratio lock?
|
Color background; ///< Color for areas outside the source image
|
||||||
|
bool allow_outside; ///< Allow the slice to extend outside the source image?
|
||||||
|
bool aspect_fixed; ///< Aspect ratio lock?
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
bool sharpen;
|
bool sharpen;
|
||||||
int sharpen_amount;
|
int sharpen_amount;
|
||||||
|
|
||||||
/// Enforce relations between values
|
/// Enforce relations between values
|
||||||
void constrain(PreferedProperty prefer = PREFER_NONE);
|
void constrain(PreferedProperty prefer = PREFER_NONE);
|
||||||
/// Attempt to center the current constraints
|
/// Attempt to center the current constraints
|
||||||
void centerSelection();
|
void centerSelection();
|
||||||
void centerSelectionHorizontally();
|
void centerSelectionHorizontally();
|
||||||
void centerSelectionVertically();
|
void centerSelectionVertically();
|
||||||
/// Get the sliced image
|
/// Get the sliced image
|
||||||
Image getSlice(double scale = 1.0) const;
|
Image getSlice(double scale = 1.0) const;
|
||||||
@@ -62,11 +65,16 @@ public:
|
|||||||
/// Dialog for selecting a slice of an image
|
/// Dialog for selecting a slice of an image
|
||||||
class ImageSliceWindow : public wxDialog {
|
class ImageSliceWindow : public wxDialog {
|
||||||
public:
|
public:
|
||||||
ImageSliceWindow(Window* parent, const Image& source, const wxSize& target_size, const AlphaMask& target_mask);
|
ImageSliceWindow(Window* parent, const Image& source, const String& filename, const String& cardname, const wxSize& target_size, const AlphaMask& target_mask);
|
||||||
|
|
||||||
/// Return the sliced image
|
/// Return the sliced image
|
||||||
Image getImage(double scale) const;
|
Image getImage(double scale) const;
|
||||||
|
|
||||||
|
// --------------------------------------------------- : Previously Used Settings
|
||||||
|
|
||||||
|
static map<String, String> previously_used_settings_path; // map from cardname to filename
|
||||||
|
static map<pair<String, String>, pair<wxRect, int>> previously_used_settings_value; // map from filename+cardname pair to settings
|
||||||
|
|
||||||
// --------------------------------------------------- : Data
|
// --------------------------------------------------- : Data
|
||||||
private:
|
private:
|
||||||
// The slice we are extracting
|
// The slice we are extracting
|
||||||
@@ -74,7 +82,7 @@ private:
|
|||||||
// Gui items
|
// Gui items
|
||||||
ImageSlicePreview* preview;
|
ImageSlicePreview* preview;
|
||||||
ImageSliceSelector* selector;
|
ImageSliceSelector* selector;
|
||||||
wxRadioBox* size;
|
wxRadioBox* size, *grid;
|
||||||
wxSpinCtrl* top, *left, *width, *height;
|
wxSpinCtrl* top, *left, *width, *height;
|
||||||
wxCheckBox* fix_aspect;
|
wxCheckBox* fix_aspect;
|
||||||
wxSpinCtrl* zoom, *zoom_x, *zoom_y;
|
wxSpinCtrl* zoom, *zoom_x, *zoom_y;
|
||||||
@@ -91,11 +99,12 @@ private:
|
|||||||
void onSize (wxSizeEvent&);
|
void onSize (wxSizeEvent&);
|
||||||
|
|
||||||
void onChangeSize (wxCommandEvent&);
|
void onChangeSize (wxCommandEvent&);
|
||||||
|
void onChangeGrid (wxCommandEvent&);
|
||||||
void onChangeLeft (wxCommandEvent&);
|
void onChangeLeft (wxCommandEvent&);
|
||||||
void onChangeTop (wxCommandEvent&);
|
void onChangeTop (wxCommandEvent&);
|
||||||
void onChangeWidth (wxCommandEvent&);
|
void onChangeWidth (wxCommandEvent&);
|
||||||
void onChangeHeight (wxCommandEvent&);
|
void onChangeHeight (wxCommandEvent&);
|
||||||
void onSelectionCenter(wxCommandEvent&);
|
void onSelectionCenter (wxCommandEvent&);
|
||||||
void onChangeFixAspect (wxCommandEvent&);
|
void onChangeFixAspect (wxCommandEvent&);
|
||||||
void onChangeZoom (wxSpinEvent&);
|
void onChangeZoom (wxSpinEvent&);
|
||||||
void onChangeZoomX (wxSpinEvent&);
|
void onChangeZoomX (wxSpinEvent&);
|
||||||
@@ -120,11 +129,13 @@ private:
|
|||||||
/// A preview of the sliced image
|
/// A preview of the sliced image
|
||||||
class ImageSlicePreview : public wxControl {
|
class ImageSlicePreview : public wxControl {
|
||||||
public:
|
public:
|
||||||
ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask);
|
ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask, const int grid);
|
||||||
|
|
||||||
/// Notify that the slice was updated
|
/// Notify that the slice was updated
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
int grid;
|
||||||
|
|
||||||
// --------------------------------------------------- : Data
|
// --------------------------------------------------- : Data
|
||||||
private:
|
private:
|
||||||
Bitmap bitmap;
|
Bitmap bitmap;
|
||||||
@@ -137,7 +148,7 @@ private:
|
|||||||
|
|
||||||
// --------------------------------------------------- : Events
|
// --------------------------------------------------- : Events
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
wxSize getBestSliceSize() const;
|
wxSize getBestSliceSize() const;
|
||||||
wxSize DoGetBestSize() const override;
|
wxSize DoGetBestSize() const override;
|
||||||
|
|
||||||
|
|||||||
@@ -182,14 +182,14 @@ SelectStyleSheetWindow::SelectStyleSheetWindow(Window* parent, const Game& game,
|
|||||||
// init controls
|
// init controls
|
||||||
stylesheet_list = new PackageList (this, ID_STYLESHEET_LIST);
|
stylesheet_list = new PackageList (this, ID_STYLESHEET_LIST);
|
||||||
wxStaticText* description = new wxStaticText(this, ID_GAME_LIST, _LABEL_1_("stylesheet not found", failed_name));
|
wxStaticText* description = new wxStaticText(this, ID_GAME_LIST, _LABEL_1_("stylesheet not found", failed_name));
|
||||||
wxStaticText* stylesheet_text = new wxStaticText(this, ID_STYLESHEET_LIST, _LABEL_("style type"));
|
wxStaticText* stylesheet_text = new wxStaticText(this, ID_STYLESHEET_LIST, _LABEL_("style type"));
|
||||||
|
|
||||||
stylesheet_filter = new FilterCtrl(this, ID_STYLESHEET_FILTER, _LABEL_("search stylesheet list"), _HELP_("search stylesheet list control"));
|
stylesheet_filter = new FilterCtrl(this, ID_STYLESHEET_FILTER, _LABEL_("search stylesheet list"), _HELP_("search stylesheet list control"));
|
||||||
stylesheet_filter->setFilter(stylesheet_filter_value);
|
stylesheet_filter->setFilter(stylesheet_filter_value);
|
||||||
|
|
||||||
// init sizer
|
// init sizer
|
||||||
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||||
s->Add(description, 0, wxALL, 4);
|
s->Add(description, 0, wxALL, 4);
|
||||||
wxSizer* s2 = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer* s2 = new wxBoxSizer(wxHORIZONTAL);
|
||||||
s2->Add(stylesheet_text, 0, wxALL & ~wxLEFT, 4);
|
s2->Add(stylesheet_text, 0, wxALL & ~wxLEFT, 4);
|
||||||
s2->AddStretchSpacer();
|
s2->AddStretchSpacer();
|
||||||
@@ -215,8 +215,8 @@ void SelectStyleSheetWindow::onStyleSheetSelect(wxCommandEvent&) {
|
|||||||
}
|
}
|
||||||
void SelectStyleSheetWindow::onStyleSheetActivate(wxCommandEvent&) {
|
void SelectStyleSheetWindow::onStyleSheetActivate(wxCommandEvent&) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectStyleSheetWindow::onStylesheetFilterUpdate(wxCommandEvent&) {
|
void SelectStyleSheetWindow::onStylesheetFilterUpdate(wxCommandEvent&) {
|
||||||
if (stylesheet_list->hasSelection()) {
|
if (stylesheet_list->hasSelection()) {
|
||||||
StyleSheetP existingStylesheetSelection = stylesheet_list->getSelection<StyleSheet>(false);
|
StyleSheetP existingStylesheetSelection = stylesheet_list->getSelection<StyleSheet>(false);
|
||||||
@@ -257,7 +257,7 @@ void SelectStyleSheetWindow::onIdle(wxIdleEvent& ev) {
|
|||||||
|
|
||||||
BEGIN_EVENT_TABLE(SelectStyleSheetWindow, wxDialog)
|
BEGIN_EVENT_TABLE(SelectStyleSheetWindow, wxDialog)
|
||||||
EVT_GALLERY_SELECT (ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetSelect)
|
EVT_GALLERY_SELECT (ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetSelect)
|
||||||
EVT_GALLERY_ACTIVATE(ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetActivate)
|
EVT_GALLERY_ACTIVATE(ID_STYLESHEET_LIST, SelectStyleSheetWindow::onStyleSheetActivate)
|
||||||
EVT_COMMAND_RANGE(ID_STYLESHEET_FILTER, ID_STYLESHEET_FILTER, wxEVT_COMMAND_TEXT_UPDATED, SelectStyleSheetWindow::onStylesheetFilterUpdate)
|
EVT_COMMAND_RANGE(ID_STYLESHEET_FILTER, ID_STYLESHEET_FILTER, wxEVT_COMMAND_TEXT_UPDATED, SelectStyleSheetWindow::onStylesheetFilterUpdate)
|
||||||
EVT_BUTTON (wxID_OK, SelectStyleSheetWindow::OnOK)
|
EVT_BUTTON (wxID_OK, SelectStyleSheetWindow::OnOK)
|
||||||
EVT_UPDATE_UI (wxID_ANY, SelectStyleSheetWindow::onUpdateUI)
|
EVT_UPDATE_UI (wxID_ANY, SelectStyleSheetWindow::onUpdateUI)
|
||||||
|
|||||||
@@ -81,15 +81,15 @@ private:
|
|||||||
const Game& game;
|
const Game& game;
|
||||||
|
|
||||||
// gui items
|
// gui items
|
||||||
PackageList* stylesheet_list;
|
PackageList* stylesheet_list;
|
||||||
|
|
||||||
FilterCtrl* stylesheet_filter;
|
FilterCtrl* stylesheet_filter;
|
||||||
String stylesheet_filter_value;
|
String stylesheet_filter_value;
|
||||||
|
|
||||||
// --------------------------------------------------- : events
|
// --------------------------------------------------- : events
|
||||||
|
|
||||||
void onStyleSheetSelect (wxCommandEvent&);
|
void onStyleSheetSelect (wxCommandEvent&);
|
||||||
void onStyleSheetActivate(wxCommandEvent&);
|
void onStyleSheetActivate(wxCommandEvent&);
|
||||||
void onStylesheetFilterUpdate(wxCommandEvent&);
|
void onStylesheetFilterUpdate(wxCommandEvent&);
|
||||||
|
|
||||||
virtual void OnOK(wxCommandEvent&);
|
virtual void OnOK(wxCommandEvent&);
|
||||||
|
|||||||
@@ -214,9 +214,9 @@ DisplayPreferencesPage::DisplayPreferencesPage(Window* parent)
|
|||||||
borders = new wxCheckBox(this, wxID_ANY, _BUTTON_("show lines"));
|
borders = new wxCheckBox(this, wxID_ANY, _BUTTON_("show lines"));
|
||||||
draw_editing = new wxCheckBox(this, wxID_ANY, _BUTTON_("show editing hints"));
|
draw_editing = new wxCheckBox(this, wxID_ANY, _BUTTON_("show editing hints"));
|
||||||
spellcheck_enabled = new wxCheckBox(this, wxID_ANY, _BUTTON_("spellcheck enabled"));
|
spellcheck_enabled = new wxCheckBox(this, wxID_ANY, _BUTTON_("spellcheck enabled"));
|
||||||
non_normal_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("zoom export"));
|
non_normal_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("zoom export"));
|
||||||
zoom = new wxComboBox(this, ID_ZOOM);
|
zoom = new wxComboBox(this, ID_ZOOM);
|
||||||
export_zoom = new wxComboBox(this, ID_EXPORT_ZOOM);
|
export_zoom = new wxComboBox(this, ID_EXPORT_ZOOM);
|
||||||
|
|
||||||
//wxButton* columns = new wxButton(this, ID_SELECT_COLUMNS, _BUTTON_("select"));
|
//wxButton* columns = new wxButton(this, ID_SELECT_COLUMNS, _BUTTON_("select"));
|
||||||
// set values
|
// set values
|
||||||
@@ -227,14 +227,14 @@ DisplayPreferencesPage::DisplayPreferencesPage(Window* parent)
|
|||||||
non_normal_export->SetValue(!settings.default_stylesheet_settings.card_normal_export());
|
non_normal_export->SetValue(!settings.default_stylesheet_settings.card_normal_export());
|
||||||
zoom_int = static_cast<int>(settings.default_stylesheet_settings.card_zoom() * 100);
|
zoom_int = static_cast<int>(settings.default_stylesheet_settings.card_zoom() * 100);
|
||||||
zoom->SetValue(String::Format(_("%d%%"),zoom_int));
|
zoom->SetValue(String::Format(_("%d%%"),zoom_int));
|
||||||
int choices[] = { 50,66,75,100,120,150,175,200 };
|
int zoom_choices[] = { 50,66,75,80,100,120,125,150,175,200 };
|
||||||
for (unsigned int i = 0 ; i < sizeof(choices)/sizeof(choices[0]) ; ++i) {
|
for (unsigned int i = 0 ; i < sizeof(zoom_choices)/sizeof(zoom_choices[0]) ; ++i) {
|
||||||
zoom->Append(String::Format(_("%d%%"),choices[i]));
|
zoom->Append(String::Format(_("%d%%"), zoom_choices[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export_zoom_int = static_cast<int>(settings.default_stylesheet_settings.export_zoom() * 100);
|
export_zoom_int = static_cast<int>(settings.default_stylesheet_settings.export_zoom() * 100);
|
||||||
export_zoom->SetValue(String::Format(_("%d%%"), export_zoom_int));
|
export_zoom->SetValue(String::Format(_("%d%%"), export_zoom_int));
|
||||||
int export_choices[] = { 50,66,75,100,120,150,175,200 };
|
int export_choices[] = { 50,66,75,80,100,120,125,150,175,200 };
|
||||||
for (unsigned int i = 0; i < sizeof(export_choices) / sizeof(export_choices[0]); ++i) {
|
for (unsigned int i = 0; i < sizeof(export_choices) / sizeof(export_choices[0]); ++i) {
|
||||||
export_zoom->Append(String::Format(_("%d%%"), export_choices[i]));
|
export_zoom->Append(String::Format(_("%d%%"), export_choices[i]));
|
||||||
}
|
}
|
||||||
@@ -328,7 +328,7 @@ InternalPreferencesPage::InternalPreferencesPage(Window* parent) : PreferencesPa
|
|||||||
internal_scale_int = static_cast<int>(settings.internal_scale * 100);
|
internal_scale_int = static_cast<int>(settings.internal_scale * 100);
|
||||||
internal_scale->SetValue(String::Format(_("%d%%"), internal_scale_int));
|
internal_scale->SetValue(String::Format(_("%d%%"), internal_scale_int));
|
||||||
|
|
||||||
int choices[] = { 100,200,300,400 };
|
int choices[] = { 100,120,125,150,175,200 };
|
||||||
for (unsigned int i = 0; i < sizeof(choices) / sizeof(choices[0]); ++i) {
|
for (unsigned int i = 0; i < sizeof(choices) / sizeof(choices[0]); ++i) {
|
||||||
internal_scale->Append(String::Format(_("%d%%"), choices[i]));
|
internal_scale->Append(String::Format(_("%d%%"), choices[i]));
|
||||||
}
|
}
|
||||||
|
|||||||
+228
-228
@@ -14,150 +14,150 @@
|
|||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <render/card/viewer.hpp>
|
#include <render/card/viewer.hpp>
|
||||||
#include <wx/print.h>
|
#include <wx/print.h>
|
||||||
#include <wx/valnum.h>
|
#include <wx/valnum.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
DECLARE_POINTER_TYPE(PageLayout);
|
DECLARE_POINTER_TYPE(PageLayout);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Layout
|
// ----------------------------------------------------------------------------- : Layout
|
||||||
|
|
||||||
void PrintJob::init(const RealSize& page_size) {
|
void PrintJob::init(const RealSize& page_size) {
|
||||||
this->page_size = page_size;
|
this->page_size = page_size;
|
||||||
if (cards.empty()) return;
|
if (cards.empty()) return;
|
||||||
measure_cards();
|
measure_cards();
|
||||||
layout_cards();
|
layout_cards();
|
||||||
align_cards();
|
align_cards();
|
||||||
center_cards();
|
center_cards();
|
||||||
}
|
}
|
||||||
void PrintJob::measure_cards() {
|
void PrintJob::measure_cards() {
|
||||||
FOR_EACH(card, cards) {
|
FOR_EACH(card, cards) {
|
||||||
const StyleSheet& stylesheet = set->stylesheetFor(card);
|
const StyleSheet& stylesheet = set->stylesheetFor(card);
|
||||||
RealSize size_px(stylesheet.card_width, stylesheet.card_height);
|
RealSize size_px(stylesheet.card_width, stylesheet.card_height);
|
||||||
RealSize size_mm(stylesheet.card_width * 25.4 / stylesheet.card_dpi, stylesheet.card_height * 25.4 / stylesheet.card_dpi);
|
RealSize size_mm(stylesheet.card_width * 25.4 / stylesheet.card_dpi, stylesheet.card_height * 25.4 / stylesheet.card_dpi);
|
||||||
Radians rotation = 0.0;
|
Radians rotation = 0.0;
|
||||||
bool rotated = abs(size_mm.width - default_size_mm.height) < abs(size_mm.height - default_size_mm.height); // try to align best to default card height
|
bool rotated = abs(size_mm.width - default_size_mm.height) < abs(size_mm.height - default_size_mm.height); // try to align best to default card height
|
||||||
if (rotated) {
|
if (rotated) {
|
||||||
swap(size_mm.width, size_mm.height);
|
swap(size_mm.width, size_mm.height);
|
||||||
swap(size_px.width, size_px.height);
|
swap(size_px.width, size_px.height);
|
||||||
rotation = rad90;
|
rotation = rad90;
|
||||||
}
|
}
|
||||||
if (abs(size_mm.width - default_size_mm.width) < threshold_size.width) size_mm.width = default_size_mm.width; // snap to default_size_mm if we are close
|
if (abs(size_mm.width - default_size_mm.width) < threshold_size.width) size_mm.width = default_size_mm.width; // snap to default_size_mm if we are close
|
||||||
if (abs(size_mm.height - default_size_mm.height) < threshold_size.height) size_mm.height = default_size_mm.height;
|
if (abs(size_mm.height - default_size_mm.height) < threshold_size.height) size_mm.height = default_size_mm.height;
|
||||||
CardLayout layout(card, size_mm, size_px, rotation);
|
CardLayout layout(card, size_mm, size_px, rotation);
|
||||||
card_layouts.push_back(layout);
|
card_layouts.push_back(layout);
|
||||||
}
|
}
|
||||||
std::sort(card_layouts.begin(), card_layouts.end());
|
std::sort(card_layouts.begin(), card_layouts.end());
|
||||||
}
|
}
|
||||||
void PrintJob::layout_cards() {
|
void PrintJob::layout_cards() {
|
||||||
page_layouts.push_back(vector<CardLayout>());
|
page_layouts.push_back(vector<CardLayout>());
|
||||||
double row_top = 0.0, row_height = 0.0, row_width = 0.0;
|
double row_top = 0.0, row_height = 0.0, row_width = 0.0;
|
||||||
unordered_set<int> already_laidout_cards;
|
unordered_set<int> already_laidout_cards;
|
||||||
while (true) {
|
while (true) {
|
||||||
// try to find a card that will fit on the current row
|
// try to find a card that will fit on the current row
|
||||||
for (int i = 0; i < card_layouts.size(); ++i) {
|
for (int i = 0; i < card_layouts.size(); ++i) {
|
||||||
if (already_laidout_cards.find(i) != already_laidout_cards.end()) continue;
|
if (already_laidout_cards.find(i) != already_laidout_cards.end()) continue;
|
||||||
if (card_layouts[i].size_mm.width + row_width >= page_size.width) continue;
|
if (card_layouts[i].size_mm.width + row_width >= page_size.width) continue;
|
||||||
if (card_layouts[i].size_mm.height + row_top >= page_size.height) continue;
|
if (card_layouts[i].size_mm.height + row_top >= page_size.height) continue;
|
||||||
// the card fits
|
// the card fits
|
||||||
card_layouts[i].pos.width = row_width;
|
card_layouts[i].pos.width = row_width;
|
||||||
card_layouts[i].pos.height = row_top;
|
card_layouts[i].pos.height = row_top;
|
||||||
page_layouts[page_layouts.size()-1].push_back(card_layouts[i]);
|
page_layouts[page_layouts.size()-1].push_back(card_layouts[i]);
|
||||||
already_laidout_cards.insert(i);
|
already_laidout_cards.insert(i);
|
||||||
if (already_laidout_cards.size() == card_layouts.size()) return;
|
if (already_laidout_cards.size() == card_layouts.size()) return;
|
||||||
// move to next spot on the row
|
// move to next spot on the row
|
||||||
row_width += card_layouts[i].size_mm.width + settings.print_spacing;
|
row_width += card_layouts[i].size_mm.width + settings.print_spacing;
|
||||||
row_height = max(row_height, card_layouts[i].size_mm.height + settings.print_spacing);
|
row_height = max(row_height, card_layouts[i].size_mm.height + settings.print_spacing);
|
||||||
goto continue_outer;
|
goto continue_outer;
|
||||||
}
|
}
|
||||||
// no card fits
|
// no card fits
|
||||||
if (row_top == 0.0 && row_height == 0.0 && row_width == 0.0) {
|
if (row_top == 0.0 && row_height == 0.0 && row_width == 0.0) {
|
||||||
// none of the remaining cards can fit on an empty page, return
|
// none of the remaining cards can fit on an empty page, return
|
||||||
page_layouts.pop_back();
|
page_layouts.pop_back();
|
||||||
queue_message(MESSAGE_WARNING, _ERROR_("cards bigger than page"));
|
queue_message(MESSAGE_WARNING, _ERROR_("cards bigger than page"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (row_height == 0.0 && row_width == 0.0) {
|
if (row_height == 0.0 && row_width == 0.0) {
|
||||||
// none of the remaining cards can fit on an empty row, create a new page
|
// none of the remaining cards can fit on an empty row, create a new page
|
||||||
page_layouts.push_back(vector<CardLayout>());
|
page_layouts.push_back(vector<CardLayout>());
|
||||||
row_top = 0.0;
|
row_top = 0.0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// none of the remaining cards can fit on this row, create a new row
|
// none of the remaining cards can fit on this row, create a new row
|
||||||
row_top += row_height;
|
row_top += row_height;
|
||||||
row_width = row_height = 0.0;
|
row_width = row_height = 0.0;
|
||||||
continue_outer:;
|
continue_outer:;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void PrintJob::align_cards() {
|
|
||||||
// for each page
|
|
||||||
for (int p = 0; p < page_layouts.size(); ++p) {
|
|
||||||
vector<CardLayout>& page_layout = page_layouts[p];
|
|
||||||
// for each card on the page
|
|
||||||
for (int max = 0, j = 0; j < page_layout.size(); ++max, ++j) {
|
|
||||||
if (max > 100) {
|
|
||||||
queue_message(MESSAGE_WARNING, _("DEBUG: large amount of iterations when aligning cards for print"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
double x = page_layout[j].pos.width;
|
|
||||||
double y = page_layout[j].pos.height;
|
|
||||||
// if another card is almost aligned
|
|
||||||
for (int i = 0; i < page_layout.size(); ++i) {
|
|
||||||
if (i == j) continue;
|
|
||||||
double difference = page_layout[i].pos.width - x;
|
|
||||||
if (threshold_bottom < difference && difference <= threshold_top) {
|
|
||||||
// get the card, and all cards to the right on the same row
|
|
||||||
vector<int> cards;
|
|
||||||
cards.push_back(j);
|
|
||||||
for (int h = 0; h < page_layout.size(); ++h) {
|
|
||||||
if (h == j) continue;
|
|
||||||
double difference_x = page_layout[h].pos.width - x;
|
|
||||||
double difference_y = abs(page_layout[h].pos.height - y);
|
|
||||||
if (difference_y < threshold_bottom && difference_x > threshold_bottom) {
|
|
||||||
cards.push_back(h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check if all these cards can be moved to the right
|
|
||||||
bool can_move = true;
|
|
||||||
for (int h = 0; h < cards.size(); ++h) {
|
|
||||||
if (page_layout[cards[h]].pos.width + page_layout[cards[h]].size_mm.width + difference > page_size.width) {
|
|
||||||
can_move = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// move the cards
|
|
||||||
if (can_move) {
|
|
||||||
for (int h = 0; h < cards.size(); ++h) {
|
|
||||||
page_layout[cards[h]].pos.width += difference;
|
|
||||||
}
|
|
||||||
j = -1; // restart, new cards may be in range now
|
|
||||||
goto continue_outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue_outer:;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void PrintJob::center_cards() {
|
void PrintJob::align_cards() {
|
||||||
for (int p = 0; p < page_layouts.size(); ++p) {
|
// for each page
|
||||||
vector<CardLayout>& page_layout = page_layouts[p];
|
for (int p = 0; p < page_layouts.size(); ++p) {
|
||||||
RealSize page_margin(0.0, 0.0);
|
vector<CardLayout>& page_layout = page_layouts[p];
|
||||||
for (int i = 0; i < page_layout.size(); ++i) {
|
// for each card on the page
|
||||||
double width = page_layout[i].pos.width + page_layout[i].size_mm.width;
|
for (int max = 0, j = 0; j < page_layout.size(); ++max, ++j) {
|
||||||
double height = page_layout[i].pos.height + page_layout[i].size_mm.height;
|
if (max > 100) {
|
||||||
if (page_margin.width < width) page_margin.width = width;
|
queue_message(MESSAGE_WARNING, _("DEBUG: large amount of iterations when aligning cards for print"));
|
||||||
if (page_margin.height < height) page_margin.height = height;
|
break;
|
||||||
}
|
}
|
||||||
page_margin.width = (page_size.width - page_margin.width) / 2;
|
double x = page_layout[j].pos.width;
|
||||||
page_margin.height = (page_size.height - page_margin.height) / 2;
|
double y = page_layout[j].pos.height;
|
||||||
page_margins.push_back(page_margin);
|
// if another card is almost aligned
|
||||||
for (int i = 0; i < page_layout.size(); ++i) {
|
for (int i = 0; i < page_layout.size(); ++i) {
|
||||||
page_layout[i].pos.width += page_margin.width;
|
if (i == j) continue;
|
||||||
page_layout[i].pos.height += page_margin.height;
|
double difference = page_layout[i].pos.width - x;
|
||||||
|
if (threshold_bottom < difference && difference <= threshold_top) {
|
||||||
|
// get the card, and all cards to the right on the same row
|
||||||
|
vector<int> cards;
|
||||||
|
cards.push_back(j);
|
||||||
|
for (int h = 0; h < page_layout.size(); ++h) {
|
||||||
|
if (h == j) continue;
|
||||||
|
double difference_x = page_layout[h].pos.width - x;
|
||||||
|
double difference_y = abs(page_layout[h].pos.height - y);
|
||||||
|
if (difference_y < threshold_bottom && difference_x > threshold_bottom) {
|
||||||
|
cards.push_back(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if all these cards can be moved to the right
|
||||||
|
bool can_move = true;
|
||||||
|
for (int h = 0; h < cards.size(); ++h) {
|
||||||
|
if (page_layout[cards[h]].pos.width + page_layout[cards[h]].size_mm.width + difference > page_size.width) {
|
||||||
|
can_move = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// move the cards
|
||||||
|
if (can_move) {
|
||||||
|
for (int h = 0; h < cards.size(); ++h) {
|
||||||
|
page_layout[cards[h]].pos.width += difference;
|
||||||
|
}
|
||||||
|
j = -1; // restart, new cards may be in range now
|
||||||
|
goto continue_outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue_outer:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void PrintJob::center_cards() {
|
||||||
|
for (int p = 0; p < page_layouts.size(); ++p) {
|
||||||
|
vector<CardLayout>& page_layout = page_layouts[p];
|
||||||
|
RealSize page_margin(0.0, 0.0);
|
||||||
|
for (int i = 0; i < page_layout.size(); ++i) {
|
||||||
|
double width = page_layout[i].pos.width + page_layout[i].size_mm.width;
|
||||||
|
double height = page_layout[i].pos.height + page_layout[i].size_mm.height;
|
||||||
|
if (page_margin.width < width) page_margin.width = width;
|
||||||
|
if (page_margin.height < height) page_margin.height = height;
|
||||||
|
}
|
||||||
|
page_margin.width = (page_size.width - page_margin.width) / 2;
|
||||||
|
page_margin.height = (page_size.height - page_margin.height) / 2;
|
||||||
|
page_margins.push_back(page_margin);
|
||||||
|
for (int i = 0; i < page_layout.size(); ++i) {
|
||||||
|
page_layout[i].pos.width += page_margin.width;
|
||||||
|
page_layout[i].pos.height += page_margin.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Printout
|
// ----------------------------------------------------------------------------- : Printout
|
||||||
|
|
||||||
@@ -182,11 +182,11 @@ private:
|
|||||||
int pageCount() {
|
int pageCount() {
|
||||||
return job->page_layouts.size();
|
return job->page_layouts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw cutter lines in the page margins, corresponding to the edges of cards
|
/// Draw cutter lines in the page margins, corresponding to the edges of cards
|
||||||
void drawCutterLines(DC& dc, PrintJobP& job, int page);
|
void drawCutterLines(DC& dc, PrintJobP& job, int page);
|
||||||
/// Draw cards according to their CardLayout info
|
/// Draw cards according to their CardLayout info
|
||||||
void drawCards (DC& dc, PrintJobP& job, int page);
|
void drawCards (DC& dc, PrintJobP& job, int page);
|
||||||
void drawCard (DC& dc, PrintJob::CardLayout& card_layout);
|
void drawCard (DC& dc, PrintJob::CardLayout& card_layout);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -224,19 +224,19 @@ bool CardsPrintout::OnPrintPage(int page) {
|
|||||||
dc.GetSize(&page_width_px, &page_height_px);
|
dc.GetSize(&page_width_px, &page_height_px);
|
||||||
// scale factor (pixels per mm)
|
// scale factor (pixels per mm)
|
||||||
printer_px_per_mm = RealSize((double)page_width_px / page_width_mm, (double)page_height_px / page_height_mm);
|
printer_px_per_mm = RealSize((double)page_width_px / page_width_mm, (double)page_height_px / page_height_mm);
|
||||||
// print the cards that belong on this page
|
// print the cards that belong on this page
|
||||||
drawCards(dc, job, page);
|
drawCards(dc, job, page);
|
||||||
if (settings.print_cutter_lines != CUTTER_NONE) drawCutterLines(dc, job, page);
|
if (settings.print_cutter_lines != CUTTER_NONE) drawCutterLines(dc, job, page);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
void CardsPrintout::drawCards(DC& dc, PrintJobP& job, int page) {
|
|
||||||
FOR_EACH(card_layout, job->page_layouts[page - 1]) {
|
|
||||||
drawCard(dc, card_layout);
|
|
||||||
}
|
|
||||||
dc.SetUserScale(printer_px_per_mm.width, printer_px_per_mm.height);
|
|
||||||
}
|
}
|
||||||
void CardsPrintout::drawCard(DC& dc, PrintJob::CardLayout& card_layout) {
|
|
||||||
|
void CardsPrintout::drawCards(DC& dc, PrintJobP& job, int page) {
|
||||||
|
FOR_EACH(card_layout, job->page_layouts[page - 1]) {
|
||||||
|
drawCard(dc, card_layout);
|
||||||
|
}
|
||||||
|
dc.SetUserScale(printer_px_per_mm.width, printer_px_per_mm.height);
|
||||||
|
}
|
||||||
|
void CardsPrintout::drawCard(DC& dc, PrintJob::CardLayout& card_layout) {
|
||||||
// draw card to its own buffer
|
// draw card to its own buffer
|
||||||
wxBitmap buffer(card_layout.size_px.width, card_layout.size_px.height, 32);
|
wxBitmap buffer(card_layout.size_px.width, card_layout.size_px.height, 32);
|
||||||
wxMemoryDC bufferDC;
|
wxMemoryDC bufferDC;
|
||||||
@@ -250,100 +250,100 @@ void CardsPrintout::drawCard(DC& dc, PrintJob::CardLayout& card_layout) {
|
|||||||
dc.SetUserScale(printer_px_per_mm.width / card_layout.px_per_mm.width, printer_px_per_mm.height / card_layout.px_per_mm.height);
|
dc.SetUserScale(printer_px_per_mm.width / card_layout.px_per_mm.width, printer_px_per_mm.height / card_layout.px_per_mm.height);
|
||||||
dc.DrawBitmap(buffer, int(card_layout.pos.width * card_layout.px_per_mm.width), int(card_layout.pos.height * card_layout.px_per_mm.height));
|
dc.DrawBitmap(buffer, int(card_layout.pos.width * card_layout.px_per_mm.width), int(card_layout.pos.height * card_layout.px_per_mm.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardsPrintout::drawCutterLines(DC& dc, PrintJobP& job, int page) {
|
void CardsPrintout::drawCutterLines(DC& dc, PrintJobP& job, int page) {
|
||||||
const vector<PrintJob::CardLayout>& page_layout = job->page_layouts[page - 1];
|
const vector<PrintJob::CardLayout>& page_layout = job->page_layouts[page - 1];
|
||||||
const RealSize& page_margin = job->page_margins[page - 1];
|
const RealSize& page_margin = job->page_margins[page - 1];
|
||||||
int page_width, page_height;
|
int page_width, page_height;
|
||||||
GetPageSizeMM(&page_width, &page_height);
|
GetPageSizeMM(&page_width, &page_height);
|
||||||
|
|
||||||
double vertical_line_size = min(10.0, page_margin.height - 3.0);
|
double vertical_line_size = min(10.0, page_margin.height - 3.0);
|
||||||
if (vertical_line_size > 0.0) {
|
if (vertical_line_size > 0.0) {
|
||||||
for (int i = 0; i < page_layout.size(); ++i) {
|
for (int i = 0; i < page_layout.size(); ++i) {
|
||||||
double left_line = page_layout[i].pos.width;
|
double left_line = page_layout[i].pos.width;
|
||||||
double right_line = left_line + page_layout[i].size_mm.width;
|
double right_line = left_line + page_layout[i].size_mm.width;
|
||||||
bool draw_left_line = true;
|
bool draw_left_line = true;
|
||||||
bool draw_right_line = true;
|
bool draw_right_line = true;
|
||||||
if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) {
|
if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) {
|
||||||
// check if another card is in the way of this cutter line
|
// check if another card is in the way of this cutter line
|
||||||
for (int j = 0; j < page_layout.size(); ++j) {
|
for (int j = 0; j < page_layout.size(); ++j) {
|
||||||
if (i == j) continue;
|
if (i == j) continue;
|
||||||
double other_left_line = page_layout[j].pos.width;
|
double other_left_line = page_layout[j].pos.width;
|
||||||
double other_right_line = other_left_line + page_layout[j].size_mm.width;
|
double other_right_line = other_left_line + page_layout[j].size_mm.width;
|
||||||
if (draw_left_line && left_line - other_left_line > job->threshold_bottom && other_right_line - left_line > job->threshold_bottom) {
|
if (draw_left_line && left_line - other_left_line > job->threshold_bottom && other_right_line - left_line > job->threshold_bottom) {
|
||||||
draw_left_line = false;
|
draw_left_line = false;
|
||||||
if (!draw_right_line) break;
|
if (!draw_right_line) break;
|
||||||
}
|
}
|
||||||
if (draw_right_line && right_line - other_left_line > job->threshold_bottom && other_right_line - right_line > job->threshold_bottom) {
|
if (draw_right_line && right_line - other_left_line > job->threshold_bottom && other_right_line - right_line > job->threshold_bottom) {
|
||||||
draw_right_line = false;
|
draw_right_line = false;
|
||||||
if (!draw_left_line) break;
|
if (!draw_left_line) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const RealSize& px_per_mm = page_layout[i].px_per_mm;
|
const RealSize& px_per_mm = page_layout[i].px_per_mm;
|
||||||
dc.SetUserScale(printer_px_per_mm.width / px_per_mm.width, printer_px_per_mm.height / px_per_mm.height);
|
dc.SetUserScale(printer_px_per_mm.width / px_per_mm.width, printer_px_per_mm.height / px_per_mm.height);
|
||||||
if (draw_left_line) {
|
if (draw_left_line) {
|
||||||
dc.DrawLine(wxPoint(px_per_mm.width * left_line, 0.0), wxPoint(px_per_mm.width * left_line, px_per_mm.height * vertical_line_size));
|
dc.DrawLine(wxPoint(px_per_mm.width * left_line, 0.0), wxPoint(px_per_mm.width * left_line, px_per_mm.height * vertical_line_size));
|
||||||
dc.DrawLine(wxPoint(px_per_mm.width * left_line, px_per_mm.height * page_height), wxPoint(px_per_mm.width * left_line, px_per_mm.height * (page_height - vertical_line_size)));
|
dc.DrawLine(wxPoint(px_per_mm.width * left_line, px_per_mm.height * page_height), wxPoint(px_per_mm.width * left_line, px_per_mm.height * (page_height - vertical_line_size)));
|
||||||
}
|
}
|
||||||
if (draw_right_line) {
|
if (draw_right_line) {
|
||||||
dc.DrawLine(wxPoint(px_per_mm.width * right_line, 0.0), wxPoint(px_per_mm.width * right_line, px_per_mm.height * vertical_line_size));
|
dc.DrawLine(wxPoint(px_per_mm.width * right_line, 0.0), wxPoint(px_per_mm.width * right_line, px_per_mm.height * vertical_line_size));
|
||||||
dc.DrawLine(wxPoint(px_per_mm.width * right_line, px_per_mm.height * page_height), wxPoint(px_per_mm.width * right_line, px_per_mm.height * (page_height - vertical_line_size)));
|
dc.DrawLine(wxPoint(px_per_mm.width * right_line, px_per_mm.height * page_height), wxPoint(px_per_mm.width * right_line, px_per_mm.height * (page_height - vertical_line_size)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
queue_message(MESSAGE_WARNING, _ERROR_("v margin too small for cutter"));
|
queue_message(MESSAGE_WARNING, _ERROR_("v margin too small for cutter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
double horizontal_line_size = min(10.0, page_margin.width - 3.0);
|
double horizontal_line_size = min(10.0, page_margin.width - 3.0);
|
||||||
if (horizontal_line_size > 0.0) {
|
if (horizontal_line_size > 0.0) {
|
||||||
for (int i = 0; i < page_layout.size(); ++i) {
|
for (int i = 0; i < page_layout.size(); ++i) {
|
||||||
double top_line = page_layout[i].pos.height;
|
double top_line = page_layout[i].pos.height;
|
||||||
double bottom_line = top_line + page_layout[i].size_mm.height;
|
double bottom_line = top_line + page_layout[i].size_mm.height;
|
||||||
bool draw_top_line = true;
|
bool draw_top_line = true;
|
||||||
bool draw_bottom_line = true;
|
bool draw_bottom_line = true;
|
||||||
if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) {
|
if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) {
|
||||||
// check if another card is in the way of this cutter line
|
// check if another card is in the way of this cutter line
|
||||||
for (int j = 0; j < page_layout.size(); ++j) {
|
for (int j = 0; j < page_layout.size(); ++j) {
|
||||||
if (i == j) continue;
|
if (i == j) continue;
|
||||||
double other_top_line = page_layout[j].pos.height;
|
double other_top_line = page_layout[j].pos.height;
|
||||||
double other_bottom_line = other_top_line + page_layout[j].size_mm.height;
|
double other_bottom_line = other_top_line + page_layout[j].size_mm.height;
|
||||||
if (draw_top_line && top_line - other_top_line > job->threshold_bottom && other_bottom_line - top_line > job->threshold_bottom) {
|
if (draw_top_line && top_line - other_top_line > job->threshold_bottom && other_bottom_line - top_line > job->threshold_bottom) {
|
||||||
draw_top_line = false;
|
draw_top_line = false;
|
||||||
if (!draw_bottom_line) break;
|
if (!draw_bottom_line) break;
|
||||||
}
|
}
|
||||||
if (draw_bottom_line && bottom_line - other_top_line > job->threshold_bottom && other_bottom_line - bottom_line > job->threshold_bottom) {
|
if (draw_bottom_line && bottom_line - other_top_line > job->threshold_bottom && other_bottom_line - bottom_line > job->threshold_bottom) {
|
||||||
draw_bottom_line = false;
|
draw_bottom_line = false;
|
||||||
if (!draw_top_line) break;
|
if (!draw_top_line) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const RealSize& px_per_mm = page_layout[i].px_per_mm;
|
const RealSize& px_per_mm = page_layout[i].px_per_mm;
|
||||||
dc.SetUserScale(printer_px_per_mm.width / px_per_mm.width, printer_px_per_mm.height / px_per_mm.height);
|
dc.SetUserScale(printer_px_per_mm.width / px_per_mm.width, printer_px_per_mm.height / px_per_mm.height);
|
||||||
if (draw_top_line) {
|
if (draw_top_line) {
|
||||||
dc.DrawLine(wxPoint(0.0, px_per_mm.height * top_line), wxPoint(px_per_mm.width * horizontal_line_size, px_per_mm.height * top_line));
|
dc.DrawLine(wxPoint(0.0, px_per_mm.height * top_line), wxPoint(px_per_mm.width * horizontal_line_size, px_per_mm.height * top_line));
|
||||||
dc.DrawLine(wxPoint(px_per_mm.width * page_width, px_per_mm.height * top_line), wxPoint(px_per_mm.width * (page_width - horizontal_line_size), px_per_mm.height * top_line));
|
dc.DrawLine(wxPoint(px_per_mm.width * page_width, px_per_mm.height * top_line), wxPoint(px_per_mm.width * (page_width - horizontal_line_size), px_per_mm.height * top_line));
|
||||||
}
|
}
|
||||||
if (draw_bottom_line) {
|
if (draw_bottom_line) {
|
||||||
dc.DrawLine(wxPoint(0.0, px_per_mm.height * bottom_line), wxPoint(px_per_mm.width * horizontal_line_size, px_per_mm.height * bottom_line));
|
dc.DrawLine(wxPoint(0.0, px_per_mm.height * bottom_line), wxPoint(px_per_mm.width * horizontal_line_size, px_per_mm.height * bottom_line));
|
||||||
dc.DrawLine(wxPoint(px_per_mm.width * page_width, px_per_mm.height * bottom_line), wxPoint(px_per_mm.width * (page_width - horizontal_line_size), px_per_mm.height * bottom_line));
|
dc.DrawLine(wxPoint(px_per_mm.width * page_width, px_per_mm.height * bottom_line), wxPoint(px_per_mm.width * (page_width - horizontal_line_size), px_per_mm.height * bottom_line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
queue_message(MESSAGE_WARNING, _ERROR_("h margin too small for cutter"));
|
queue_message(MESSAGE_WARNING, _ERROR_("h margin too small for cutter"));
|
||||||
}
|
}
|
||||||
dc.SetUserScale(printer_px_per_mm.width, printer_px_per_mm.height);
|
dc.SetUserScale(printer_px_per_mm.width, printer_px_per_mm.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : PrintWindow
|
// ----------------------------------------------------------------------------- : PrintWindow
|
||||||
|
|
||||||
PrintJobP make_print_job(Window* parent, const SetP& set, const ExportCardSelectionChoices& choices) {
|
PrintJobP make_print_job(Window* parent, const SetP& set, const ExportCardSelectionChoices& choices) {
|
||||||
// Let the user choose cards and spacing
|
// Let the user choose cards and spacing
|
||||||
// controls
|
// controls
|
||||||
ExportWindowBase wnd(parent, _TITLE_("select cards print"), set, choices);
|
ExportWindowBase wnd(parent, _TITLE_("select cards print"), set, choices);
|
||||||
wxFloatingPointValidator<float> validator(2, NULL, wxNUM_VAL_ZERO_AS_BLANK);
|
wxFloatingPointValidator<float> validator(2, NULL, wxNUM_VAL_ZERO_AS_BLANK);
|
||||||
validator.SetRange(0, 100);
|
validator.SetRange(0, 100);
|
||||||
wxTextCtrl* space = new wxTextCtrl(&wnd, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, 0L, validator);
|
wxTextCtrl* space = new wxTextCtrl(&wnd, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, 0L, validator);
|
||||||
space->SetValue(wxString::Format(wxT("%lf"), settings.print_spacing));
|
space->SetValue(wxString::Format(wxT("%lf"), settings.print_spacing));
|
||||||
wxChoice* cutter = new wxChoice(&wnd, wxID_ANY);
|
wxChoice* cutter = new wxChoice(&wnd, wxID_ANY);
|
||||||
cutter->Clear();
|
cutter->Clear();
|
||||||
@@ -371,10 +371,10 @@ PrintJobP make_print_job(Window* parent, const SetP& set, const ExportCardSelect
|
|||||||
if (wnd.ShowModal() != wxID_OK) {
|
if (wnd.ShowModal() != wxID_OK) {
|
||||||
return PrintJobP(); // cancel
|
return PrintJobP(); // cancel
|
||||||
} else {
|
} else {
|
||||||
// save settings, make print job
|
// save settings, make print job
|
||||||
String spacing = space->GetValue();
|
String spacing = space->GetValue();
|
||||||
if (spacing.empty()) spacing = _("0");
|
if (spacing.empty()) spacing = _("0");
|
||||||
spacing.ToDouble(&settings.print_spacing);
|
spacing.ToDouble(&settings.print_spacing);
|
||||||
settings.print_cutter_lines = (CutterLinesType)cutter->GetSelection();
|
settings.print_cutter_lines = (CutterLinesType)cutter->GetSelection();
|
||||||
PrintJobP job = make_intrusive<PrintJob>(set, wnd.getSelection());
|
PrintJobP job = make_intrusive<PrintJob>(set, wnd.getSelection());
|
||||||
return job;
|
return job;
|
||||||
|
|||||||
+252
-70
@@ -25,6 +25,7 @@
|
|||||||
#include <util/tagged_string.hpp>
|
#include <util/tagged_string.hpp>
|
||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <wx/splitter.h>
|
#include <wx/splitter.h>
|
||||||
|
#include <wx/gbsizer.h>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : CardsPanel
|
// ----------------------------------------------------------------------------- : CardsPanel
|
||||||
|
|
||||||
@@ -32,15 +33,36 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
|||||||
: SetWindowPanel(parent, id)
|
: SetWindowPanel(parent, id)
|
||||||
{
|
{
|
||||||
// init controls
|
// init controls
|
||||||
editor = new CardEditor(this, ID_EDITOR);
|
editor = new CardEditor(this, ID_EDITOR);
|
||||||
splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
link_editor = new CardEditor(this, ID_CARD_LINK_EDITOR);
|
||||||
card_list = new FilteredImageCardList(splitter, ID_CARD_LIST);
|
focused_editor = editor;
|
||||||
nodes_panel = new wxPanel(splitter, wxID_ANY);
|
link_viewer_1 = new CardViewer(this, ID_CARD_LINK_VIEWER);
|
||||||
notes = new TextCtrl(nodes_panel, ID_NOTES, true);
|
link_viewer_2 = new CardViewer(this, ID_CARD_LINK_VIEWER);
|
||||||
collapse_notes = new HoverButton(nodes_panel, ID_COLLAPSE_NOTES, _("btn_collapse"), Color(), false);
|
link_viewer_3 = new CardViewer(this, ID_CARD_LINK_VIEWER);
|
||||||
|
link_viewer_4 = new CardViewer(this, ID_CARD_LINK_VIEWER);
|
||||||
|
link_relation_1 = new wxStaticText(this, ID_CARD_LINK_RELATION_1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||||
|
link_relation_2 = new wxStaticText(this, ID_CARD_LINK_RELATION_2, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||||
|
link_relation_3 = new wxStaticText(this, ID_CARD_LINK_RELATION_3, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||||
|
link_relation_4 = new wxStaticText(this, ID_CARD_LINK_RELATION_4, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||||
|
link_select = new wxButton(this, ID_CARD_LINK_SELECT, _BUTTON_("link select"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||||
|
link_unlink_1 = new wxButton(this, ID_CARD_LINK_UNLINK_1, _BUTTON_("unlink"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||||
|
link_unlink_2 = new wxButton(this, ID_CARD_LINK_UNLINK_2, _BUTTON_("unlink"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||||
|
link_unlink_3 = new wxButton(this, ID_CARD_LINK_UNLINK_3, _BUTTON_("unlink"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||||
|
link_unlink_4 = new wxButton(this, ID_CARD_LINK_UNLINK_4, _BUTTON_("unlink"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||||
|
splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||||
|
card_list = new FilteredImageCardList(splitter, ID_CARD_LIST);
|
||||||
|
nodes_panel = new wxPanel(splitter, wxID_ANY);
|
||||||
|
notes = new TextCtrl(nodes_panel, ID_NOTES, true);
|
||||||
|
collapse_notes = new HoverButton(nodes_panel, ID_COLLAPSE_NOTES, _("btn_collapse"), Color(), false);
|
||||||
collapse_notes->SetExtraStyle(wxWS_EX_PROCESS_UI_UPDATES);
|
collapse_notes->SetExtraStyle(wxWS_EX_PROCESS_UI_UPDATES);
|
||||||
filter = nullptr;
|
filter = nullptr;
|
||||||
editor->next_in_tab_order = card_list;
|
editor->next_in_tab_order = card_list;
|
||||||
|
wxFont font = link_relation_1->GetFont();
|
||||||
|
font.SetWeight(wxFONTWEIGHT_BOLD);
|
||||||
|
link_relation_1->SetFont(font);
|
||||||
|
link_relation_2->SetFont(font);
|
||||||
|
link_relation_3->SetFont(font);
|
||||||
|
link_relation_4->SetFont(font);
|
||||||
// init sizer for notes panel
|
// init sizer for notes panel
|
||||||
wxSizer* sn = new wxBoxSizer(wxVERTICAL);
|
wxSizer* sn = new wxBoxSizer(wxVERTICAL);
|
||||||
wxSizer* sc = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer* sc = new wxBoxSizer(wxHORIZONTAL);
|
||||||
@@ -54,10 +76,46 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
|||||||
splitter->SetSashGravity(1.0);
|
splitter->SetSashGravity(1.0);
|
||||||
splitter->SplitHorizontally(card_list, nodes_panel, -40);
|
splitter->SplitHorizontally(card_list, nodes_panel, -40);
|
||||||
notes_below_editor = false;
|
notes_below_editor = false;
|
||||||
// init sizer
|
// init sizer for editors and viewers
|
||||||
wxSizer* s = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer* s = new wxBoxSizer(wxHORIZONTAL); // Global Sizer
|
||||||
s_left = new wxBoxSizer(wxVERTICAL);
|
s_left = new wxBoxSizer(wxVERTICAL); // Sizer for the selected card, and it's linked cards
|
||||||
s_left->Add(editor);
|
wxSizer* card_and_link = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
s_left->Add(card_and_link);
|
||||||
|
card_and_link->Add(editor);
|
||||||
|
wxGridBagSizer* link_boxes = new wxGridBagSizer(); // Sizer for the linked cards
|
||||||
|
card_and_link->Add(link_boxes, 0, wxLEFT, 2);
|
||||||
|
link_box_1 = new wxStaticBoxSizer(wxVERTICAL, this); // Box around the first linked card, it's relation, and buttons to select and unlink
|
||||||
|
link_boxes->Add(link_box_1, wxGBPosition(0, 0), wxGBSpan(1, 1));
|
||||||
|
link_box_2 = new wxStaticBoxSizer(wxVERTICAL, this); // Box around the second linked card, it's relation, and a button to unlink
|
||||||
|
link_boxes->Add(link_box_2, wxGBPosition(1, 0), wxGBSpan(1, 1));
|
||||||
|
link_box_3 = new wxStaticBoxSizer(wxVERTICAL, this); // Box around the third linked card, it's relation, and a button to unlink
|
||||||
|
link_boxes->Add(link_box_3, wxGBPosition(0, 1), wxGBSpan(1, 1));
|
||||||
|
link_box_4 = new wxStaticBoxSizer(wxVERTICAL, this); // Box around the fourth linked card, it's relation, and a button to unlink
|
||||||
|
link_boxes->Add(link_box_4, wxGBPosition(1, 1), wxGBSpan(1, 1));
|
||||||
|
wxGridBagSizer* link_grid_1 = new wxGridBagSizer(); // Sizer for the first linked card, with it's relation, and a button to unlink
|
||||||
|
link_box_1->Add(link_grid_1);
|
||||||
|
wxGridBagSizer* link_grid_2 = new wxGridBagSizer();
|
||||||
|
link_box_2->Add(link_grid_2);
|
||||||
|
wxGridBagSizer* link_grid_3 = new wxGridBagSizer();
|
||||||
|
link_box_3->Add(link_grid_3);
|
||||||
|
wxGridBagSizer* link_grid_4 = new wxGridBagSizer();
|
||||||
|
link_box_4->Add(link_grid_4);
|
||||||
|
wxSizer* link_grid_1_buttons = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
link_grid_1->Add(link_relation_1, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxLEFT, 4);
|
||||||
|
link_grid_1->Add(link_viewer_1, wxGBPosition(1, 0), wxGBSpan(1, 2));
|
||||||
|
link_grid_1->Add(link_editor, wxGBPosition(2, 0), wxGBSpan(1, 2));
|
||||||
|
link_grid_1->Add(link_grid_1_buttons, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALIGN_RIGHT);
|
||||||
|
link_grid_1_buttons->Add(link_select);
|
||||||
|
link_grid_1_buttons->Add(link_unlink_1);
|
||||||
|
link_grid_2->Add(link_relation_2, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxLEFT, 4);
|
||||||
|
link_grid_2->Add(link_unlink_2, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALIGN_RIGHT);
|
||||||
|
link_grid_2->Add(link_viewer_2, wxGBPosition(1, 0), wxGBSpan(1, 2));
|
||||||
|
link_grid_3->Add(link_relation_3, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxLEFT, 4);
|
||||||
|
link_grid_3->Add(link_unlink_3, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALIGN_RIGHT);
|
||||||
|
link_grid_3->Add(link_viewer_3, wxGBPosition(1, 0), wxGBSpan(1, 2));
|
||||||
|
link_grid_4->Add(link_relation_4, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxLEFT, 4);
|
||||||
|
link_grid_4->Add(link_unlink_4, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALIGN_RIGHT);
|
||||||
|
link_grid_4->Add(link_viewer_4, wxGBPosition(1, 0), wxGBSpan(1, 2));
|
||||||
s->Add(s_left, 0, wxEXPAND | wxRIGHT, 2);
|
s->Add(s_left, 0, wxEXPAND | wxRIGHT, 2);
|
||||||
s->Add(splitter, 1, wxEXPAND);
|
s->Add(splitter, 1, wxEXPAND);
|
||||||
s->SetSizeHints(this);
|
s->SetSizeHints(this);
|
||||||
@@ -77,6 +135,8 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
|||||||
add_menu_item(menuCard, ID_CARD_ADD_JSON, "card_add_multiple", _MENU_("add card json") + _(" "), _HELP_("add card json"));
|
add_menu_item(menuCard, ID_CARD_ADD_JSON, "card_add_multiple", _MENU_("add card json") + _(" "), _HELP_("add card json"));
|
||||||
add_menu_item_tr(menuCard, ID_CARD_ADD, "card_add", "add_card");
|
add_menu_item_tr(menuCard, ID_CARD_ADD, "card_add", "add_card");
|
||||||
add_menu_item(menuCard, ID_CARD_REMOVE, "card_del", _MENU_("remove card")+_(" "), _HELP_("remove card"));
|
add_menu_item(menuCard, ID_CARD_REMOVE, "card_del", _MENU_("remove card")+_(" "), _HELP_("remove card"));
|
||||||
|
add_menu_item(menuCard, ID_CARD_LINK, "card_link", _MENU_("link card") + _(" "), _HELP_("link card"));
|
||||||
|
add_menu_item(menuCard, ID_CARD_AND_LINK_COPY, "card_copy", _MENU_("copy card and links") + _(" "), _HELP_("copy card and links"));
|
||||||
menuCard->AppendSeparator();
|
menuCard->AppendSeparator();
|
||||||
auto menuRotate = new wxMenu();
|
auto menuRotate = new wxMenu();
|
||||||
add_menu_item_tr(menuRotate, ID_CARD_ROTATE_0, "card_rotate_0", "rotate_0", wxITEM_CHECK);
|
add_menu_item_tr(menuRotate, ID_CARD_ROTATE_0, "card_rotate_0", "rotate_0", wxITEM_CHECK);
|
||||||
@@ -90,7 +150,7 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
|||||||
|
|
||||||
menuFormat = new wxMenu();
|
menuFormat = new wxMenu();
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_BOLD, "bold", "bold", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_BOLD, "bold", "bold", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_ITALIC, "italic", "italic", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_ITALIC, "italic", "italic", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_UNDERLINE, "underline", "underline", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_UNDERLINE, "underline", "underline", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_SYMBOL, "symbol", "symbols", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_SYMBOL, "symbol", "symbols", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_REMINDER, "reminder", "reminder_text", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_REMINDER, "reminder", "reminder_text", wxITEM_CHECK);
|
||||||
@@ -99,38 +159,38 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
|||||||
menuFormat->Append(insertSymbolMenu);
|
menuFormat->Append(insertSymbolMenu);
|
||||||
|
|
||||||
toolAddCard = nullptr;
|
toolAddCard = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardsPanel::updateCardCounts() {
|
void CardsPanel::updateCardCounts() {
|
||||||
if (counts && card_list && set) {
|
if (counts && card_list && set) {
|
||||||
int selected = card_list->GetSelectedItemCount();
|
int selected = card_list->GetSelectedItemCount();
|
||||||
int filtered = card_list->GetItemCount();
|
int filtered = card_list->GetItemCount();
|
||||||
int total = set->cards.size();
|
int total = set->cards.size();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
selected_cards_count == selected
|
selected_cards_count == selected
|
||||||
&& filtered_cards_count == filtered
|
&& filtered_cards_count == filtered
|
||||||
&& total_cards_count == total
|
&& total_cards_count == total
|
||||||
&& !counts->GetLabel().empty()
|
&& !counts->GetLabel().empty()
|
||||||
) return;
|
) return;
|
||||||
|
|
||||||
selected_cards_count = selected;
|
selected_cards_count = selected;
|
||||||
filtered_cards_count = filtered;
|
filtered_cards_count = filtered;
|
||||||
total_cards_count = total;
|
total_cards_count = total;
|
||||||
|
|
||||||
if (filtered == total) {
|
if (filtered == total) {
|
||||||
counts->SetLabel(_TOOL_2_("card counts 2",
|
counts->SetLabel(_TOOL_2_("card counts 2",
|
||||||
wxString::Format(wxT("%i"), selected),
|
wxString::Format(wxT("%i"), selected),
|
||||||
wxString::Format(wxT("%i"), total)));
|
wxString::Format(wxT("%i"), total)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
counts->SetLabel(_TOOL_3_("card counts 3",
|
counts->SetLabel(_TOOL_3_("card counts 3",
|
||||||
wxString::Format(wxT("%i"), selected),
|
wxString::Format(wxT("%i"), selected),
|
||||||
wxString::Format(wxT("%i"), filtered),
|
wxString::Format(wxT("%i"), filtered),
|
||||||
wxString::Format(wxT("%i"), total)));
|
wxString::Format(wxT("%i"), total)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardsPanel::updateNotesPosition() {
|
void CardsPanel::updateNotesPosition() {
|
||||||
wxSize editor_size = editor->GetBestSize();
|
wxSize editor_size = editor->GetBestSize();
|
||||||
@@ -177,6 +237,11 @@ CardsPanel::~CardsPanel() {
|
|||||||
|
|
||||||
void CardsPanel::onChangeSet() {
|
void CardsPanel::onChangeSet() {
|
||||||
editor->setSet(set);
|
editor->setSet(set);
|
||||||
|
link_editor->setSet(set);
|
||||||
|
link_viewer_1->setSet(set);
|
||||||
|
link_viewer_2->setSet(set);
|
||||||
|
link_viewer_3->setSet(set);
|
||||||
|
link_viewer_4->setSet(set);
|
||||||
notes->setSet(set);
|
notes->setSet(set);
|
||||||
card_list->setSet(set);
|
card_list->setSet(set);
|
||||||
|
|
||||||
@@ -187,9 +252,9 @@ void CardsPanel::onChangeSet() {
|
|||||||
menuCard->Remove(ID_CARD_ADD_MULT);
|
menuCard->Remove(ID_CARD_ADD_MULT);
|
||||||
((wxMenu*)menuCard)->Insert(4,insertManyCardsMenu); // HACK: the position is hardcoded
|
((wxMenu*)menuCard)->Insert(4,insertManyCardsMenu); // HACK: the position is hardcoded
|
||||||
// also for the toolbar dropdown menu
|
// also for the toolbar dropdown menu
|
||||||
if (toolAddCard) {
|
if (toolAddCard) {
|
||||||
// Originally this was using the menu directly, but there are compatibility issues apparently.
|
// Originally this was using the menu directly, but there are compatibility issues apparently.
|
||||||
// At this point it might be possible to just store a reference to the toolbar directly instead.
|
// At this point it might be possible to just store a reference to the toolbar directly instead.
|
||||||
toolAddCard->GetToolBar()->SetDropdownMenu(ID_CARD_ADD, makeAddCardsSubmenu(true));
|
toolAddCard->GetToolBar()->SetDropdownMenu(ID_CARD_ADD, makeAddCardsSubmenu(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,7 +283,7 @@ wxMenu* CardsPanel::makeAddCardsSubmenu(bool add_single_card_option) {
|
|||||||
void CardsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
void CardsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||||
// Toolbar
|
// Toolbar
|
||||||
add_tool_tr(tb, ID_FORMAT_BOLD, "bold", "bold", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_BOLD, "bold", "bold", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_ITALIC, "italic", "italic", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_ITALIC, "italic", "italic", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_UNDERLINE, "underline", "underline", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_UNDERLINE, "underline", "underline", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_SYMBOL, "symbol", "symbols", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_SYMBOL, "symbol", "symbols", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_REMINDER, "reminder", "reminder_text", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_REMINDER, "reminder", "reminder_text", false, wxITEM_CHECK);
|
||||||
@@ -226,6 +291,7 @@ void CardsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
toolAddCard = add_tool_tr(tb, ID_CARD_ADD, "card_add", "add_card", false, wxITEM_DROPDOWN);
|
toolAddCard = add_tool_tr(tb, ID_CARD_ADD, "card_add", "add_card", false, wxITEM_DROPDOWN);
|
||||||
tb->SetDropdownMenu(ID_CARD_ADD, makeAddCardsSubmenu(true));
|
tb->SetDropdownMenu(ID_CARD_ADD, makeAddCardsSubmenu(true));
|
||||||
add_tool_tr(tb, ID_CARD_REMOVE, "card_del", "remove_card");
|
add_tool_tr(tb, ID_CARD_REMOVE, "card_del", "remove_card");
|
||||||
|
add_tool_tr(tb, ID_CARD_LINK, "card_link", "link_card");
|
||||||
tb->AddSeparator();
|
tb->AddSeparator();
|
||||||
add_tool_tr(tb, ID_CARD_ROTATE, "card_rotate", "rotate_card", false, wxITEM_DROPDOWN);
|
add_tool_tr(tb, ID_CARD_ROTATE, "card_rotate", "rotate_card", false, wxITEM_DROPDOWN);
|
||||||
auto menuRotate = new wxMenu();
|
auto menuRotate = new wxMenu();
|
||||||
@@ -239,10 +305,10 @@ void CardsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
assert(!filter);
|
assert(!filter);
|
||||||
filter = new FilterCtrl(tb, ID_CARD_FILTER, _TOOL_("search cards"), _HELP_("search cards control"));
|
filter = new FilterCtrl(tb, ID_CARD_FILTER, _TOOL_("search cards"), _HELP_("search cards control"));
|
||||||
filter->setFilter(filter_value);
|
filter->setFilter(filter_value);
|
||||||
tb->AddControl(filter);
|
tb->AddControl(filter);
|
||||||
counts = new wxStaticText(tb, ID_CARD_COUNTER, _(""));
|
counts = new wxStaticText(tb, ID_CARD_COUNTER, _(""));
|
||||||
updateCardCounts();
|
updateCardCounts();
|
||||||
tb->AddControl(counts);
|
tb->AddControl(counts);
|
||||||
tb->Realize();
|
tb->Realize();
|
||||||
// Menus
|
// Menus
|
||||||
mb->Insert(2, menuCard, _MENU_("cards"));
|
mb->Insert(2, menuCard, _MENU_("cards"));
|
||||||
@@ -252,12 +318,13 @@ void CardsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
void CardsPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
void CardsPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||||
// Toolbar
|
// Toolbar
|
||||||
tb->DeleteTool(ID_FORMAT_BOLD);
|
tb->DeleteTool(ID_FORMAT_BOLD);
|
||||||
tb->DeleteTool(ID_FORMAT_ITALIC);
|
tb->DeleteTool(ID_FORMAT_ITALIC);
|
||||||
tb->DeleteTool(ID_FORMAT_UNDERLINE);
|
tb->DeleteTool(ID_FORMAT_UNDERLINE);
|
||||||
tb->DeleteTool(ID_FORMAT_SYMBOL);
|
tb->DeleteTool(ID_FORMAT_SYMBOL);
|
||||||
tb->DeleteTool(ID_FORMAT_REMINDER);
|
tb->DeleteTool(ID_FORMAT_REMINDER);
|
||||||
tb->DeleteTool(ID_CARD_ADD);
|
tb->DeleteTool(ID_CARD_ADD);
|
||||||
tb->DeleteTool(ID_CARD_REMOVE);
|
tb->DeleteTool(ID_CARD_REMOVE);
|
||||||
|
tb->DeleteTool(ID_CARD_LINK);
|
||||||
tb->DeleteTool(ID_CARD_ROTATE);
|
tb->DeleteTool(ID_CARD_ROTATE);
|
||||||
tb->DeleteTool(ID_CARD_COUNTER);
|
tb->DeleteTool(ID_CARD_COUNTER);
|
||||||
// remember the value in the filter control, because the card list remains filtered
|
// remember the value in the filter control, because the card list remains filtered
|
||||||
@@ -277,8 +344,8 @@ void CardsPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
|
|
||||||
void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) {
|
void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) {
|
||||||
switch (ev.GetId()) {
|
switch (ev.GetId()) {
|
||||||
case ID_CARD_PREV: ev.Enable(card_list->canSelectPrevious()); break;
|
case ID_CARD_PREV: ev.Enable(card_list->canSelectPrevious()); break;
|
||||||
case ID_CARD_NEXT: ev.Enable(card_list->canSelectNext()); break;
|
case ID_CARD_NEXT: ev.Enable(card_list->canSelectNext()); break;
|
||||||
case ID_CARD_ROTATE_0: case ID_CARD_ROTATE_90: case ID_CARD_ROTATE_180: case ID_CARD_ROTATE_270: {
|
case ID_CARD_ROTATE_0: case ID_CARD_ROTATE_90: case ID_CARD_ROTATE_180: case ID_CARD_ROTATE_270: {
|
||||||
StyleSheetSettings& ss = settings.stylesheetSettingsFor(set->stylesheetFor(card_list->getCard()));
|
StyleSheetSettings& ss = settings.stylesheetSettingsFor(set->stylesheetFor(card_list->getCard()));
|
||||||
int a = ev.GetId() == ID_CARD_ROTATE_0 ? 0
|
int a = ev.GetId() == ID_CARD_ROTATE_0 ? 0
|
||||||
@@ -292,11 +359,16 @@ void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) {
|
|||||||
ev.Enable(insertManyCardsMenu->GetSubMenu() != nullptr);
|
ev.Enable(insertManyCardsMenu->GetSubMenu() != nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ID_CARD_REMOVE: ev.Enable(card_list->canDelete()); break;
|
case ID_CARD_REMOVE: ev.Enable(card_list->canDelete()); break;
|
||||||
|
case ID_CARD_LINK: ev.Enable(card_list->canLink()); break;
|
||||||
|
case ID_CARD_AND_LINK_COPY: ev.Enable(card_list->canCopy()); break;
|
||||||
case ID_FORMAT_BOLD: case ID_FORMAT_ITALIC: case ID_FORMAT_UNDERLINE: case ID_FORMAT_SYMBOL: case ID_FORMAT_REMINDER: {
|
case ID_FORMAT_BOLD: case ID_FORMAT_ITALIC: case ID_FORMAT_UNDERLINE: case ID_FORMAT_SYMBOL: case ID_FORMAT_REMINDER: {
|
||||||
if (focused_control(this) == ID_EDITOR) {
|
if (focused_control(this) == ID_EDITOR) {
|
||||||
ev.Enable(editor->canFormat(ev.GetId()));
|
ev.Enable(editor->canFormat(ev.GetId()));
|
||||||
ev.Check (editor->hasFormat(ev.GetId()));
|
ev.Check (editor->hasFormat(ev.GetId()));
|
||||||
|
} else if (focused_control(this) == ID_CARD_LINK_EDITOR) {
|
||||||
|
ev.Enable(link_editor->canFormat(ev.GetId()));
|
||||||
|
ev.Check (link_editor->hasFormat(ev.GetId()));
|
||||||
} else {
|
} else {
|
||||||
ev.Enable(false);
|
ev.Enable(false);
|
||||||
ev.Check(false);
|
ev.Check(false);
|
||||||
@@ -313,18 +385,18 @@ void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) {
|
|||||||
case ID_INSERT_SYMBOL: ev.Enable(false); break;
|
case ID_INSERT_SYMBOL: ev.Enable(false); break;
|
||||||
#else
|
#else
|
||||||
case ID_INSERT_SYMBOL: {
|
case ID_INSERT_SYMBOL: {
|
||||||
wxMenu* menu = editor->getMenu(ID_INSERT_SYMBOL);
|
wxMenu* menu = focused_editor->getMenu(ID_INSERT_SYMBOL);
|
||||||
ev.Enable(menu);
|
ev.Enable(menu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
updateCardCounts();
|
updateCardCounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardsPanel::onMenuOpen(wxMenuEvent& ev) {
|
void CardsPanel::onMenuOpen(wxMenuEvent& ev) {
|
||||||
if (ev.GetMenu() != menuFormat) return;
|
if (ev.GetMenu() != menuFormat) return;
|
||||||
wxMenu* menu = editor->getMenu(ID_INSERT_SYMBOL);
|
wxMenu* menu = focused_editor->getMenu(ID_INSERT_SYMBOL);
|
||||||
if (insertSymbolMenu->GetSubMenu() != menu || (menu && menu->GetParent() != menuFormat)) {
|
if (insertSymbolMenu->GetSubMenu() != menu || (menu && menu->GetParent() != menuFormat)) {
|
||||||
// re-add the menu
|
// re-add the menu
|
||||||
menuFormat->Remove(ID_INSERT_SYMBOL);
|
menuFormat->Remove(ID_INSERT_SYMBOL);
|
||||||
@@ -358,6 +430,27 @@ void CardsPanel::onCommand(int id) {
|
|||||||
case ID_CARD_REMOVE:
|
case ID_CARD_REMOVE:
|
||||||
card_list->doDelete();
|
card_list->doDelete();
|
||||||
break;
|
break;
|
||||||
|
case ID_CARD_LINK:
|
||||||
|
card_list->doLink();
|
||||||
|
setCard(card_list->getCard(), true);
|
||||||
|
break;
|
||||||
|
case ID_CARD_LINK_UNLINK_1: case ID_CARD_LINK_UNLINK_2: case ID_CARD_LINK_UNLINK_3: case ID_CARD_LINK_UNLINK_4: {
|
||||||
|
card_list->doUnlink((
|
||||||
|
id == ID_CARD_LINK_UNLINK_1 ? link_viewer_1
|
||||||
|
: id == ID_CARD_LINK_UNLINK_2 ? link_viewer_2
|
||||||
|
: id == ID_CARD_LINK_UNLINK_3 ? link_viewer_3
|
||||||
|
: link_viewer_4
|
||||||
|
)->getCard());
|
||||||
|
setCard(card_list->getCard(), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ID_CARD_LINK_SELECT: {
|
||||||
|
setCard(link_viewer_1->getCard(), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ID_CARD_AND_LINK_COPY:
|
||||||
|
card_list->doCopyCardAndLinkedCards();
|
||||||
|
break;
|
||||||
case ID_CARD_ROTATE:
|
case ID_CARD_ROTATE:
|
||||||
case ID_CARD_ROTATE_0: case ID_CARD_ROTATE_90: case ID_CARD_ROTATE_180: case ID_CARD_ROTATE_270: {
|
case ID_CARD_ROTATE_0: case ID_CARD_ROTATE_90: case ID_CARD_ROTATE_180: case ID_CARD_ROTATE_270: {
|
||||||
StyleSheetSettings& ss = settings.stylesheetSettingsFor(set->stylesheetFor(card_list->getCard()));
|
StyleSheetSettings& ss = settings.stylesheetSettingsFor(set->stylesheetFor(card_list->getCard()));
|
||||||
@@ -378,6 +471,9 @@ void CardsPanel::onCommand(int id) {
|
|||||||
if (focused_control(this) == ID_EDITOR) {
|
if (focused_control(this) == ID_EDITOR) {
|
||||||
editor->doFormat(id);
|
editor->doFormat(id);
|
||||||
}
|
}
|
||||||
|
else if (focused_control(this) == ID_CARD_LINK_EDITOR) {
|
||||||
|
link_editor->doFormat(id);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ID_COLLAPSE_NOTES: {
|
case ID_COLLAPSE_NOTES: {
|
||||||
@@ -399,7 +495,7 @@ void CardsPanel::onCommand(int id) {
|
|||||||
default: {
|
default: {
|
||||||
if (id >= ID_INSERT_SYMBOL_MENU_MIN && id <= ID_INSERT_SYMBOL_MENU_MAX) {
|
if (id >= ID_INSERT_SYMBOL_MENU_MIN && id <= ID_INSERT_SYMBOL_MENU_MAX) {
|
||||||
// pass on to editor
|
// pass on to editor
|
||||||
editor->onCommand(id);
|
focused_editor->onCommand(id);
|
||||||
} else if (id >= ID_ADD_CARDS_MENU_MIN && id <= ID_ADD_CARDS_MENU_MAX) {
|
} else if (id >= ID_ADD_CARDS_MENU_MIN && id <= ID_ADD_CARDS_MENU_MAX) {
|
||||||
// add multiple cards
|
// add multiple cards
|
||||||
AddCardsScriptP script = set->game->add_cards_scripts.at(id - ID_ADD_CARDS_MENU_MIN);
|
AddCardsScriptP script = set->game->add_cards_scripts.at(id - ID_ADD_CARDS_MENU_MIN);
|
||||||
@@ -420,10 +516,11 @@ bool CardsPanel::wantsToHandle(const Action&, bool undone) const {
|
|||||||
// determine what control to use for clipboard actions
|
// determine what control to use for clipboard actions
|
||||||
#define CUT_COPY_PASTE(op,return) \
|
#define CUT_COPY_PASTE(op,return) \
|
||||||
int id = focused_control(this); \
|
int id = focused_control(this); \
|
||||||
if (id == ID_EDITOR) { return editor->op(); } \
|
if (id == ID_EDITOR) { return editor->op(); } \
|
||||||
else if (id == ID_CARD_LIST) { return card_list->op(); } \
|
else if (id == ID_CARD_LINK_EDITOR) { return link_editor->op(); } \
|
||||||
else if (id == ID_NOTES) { return notes->op(); } \
|
else if (id == ID_CARD_LIST) { return card_list->op(); } \
|
||||||
else { return false; }
|
else if (id == ID_NOTES) { return notes->op(); } \
|
||||||
|
else { return false; }
|
||||||
|
|
||||||
bool CardsPanel::canCut() const { CUT_COPY_PASTE(canCut, return) }
|
bool CardsPanel::canCut() const { CUT_COPY_PASTE(canCut, return) }
|
||||||
bool CardsPanel::canCopy() const { CUT_COPY_PASTE(canCopy, return) }
|
bool CardsPanel::canCopy() const { CUT_COPY_PASTE(canCopy, return) }
|
||||||
@@ -434,17 +531,19 @@ void CardsPanel::doCopy() { CUT_COPY_PASTE(doCopy, return (void)) }
|
|||||||
bool CardsPanel::canPaste() const {
|
bool CardsPanel::canPaste() const {
|
||||||
if (card_list->canPaste()) return true;
|
if (card_list->canPaste()) return true;
|
||||||
int id = focused_control(this);
|
int id = focused_control(this);
|
||||||
if (id == ID_EDITOR) return editor->canPaste();
|
if (id == ID_EDITOR) return editor->canPaste();
|
||||||
else if (id == ID_NOTES) return notes->canPaste();
|
else if (id == ID_CARD_LINK_EDITOR) return link_editor->canPaste();
|
||||||
else return false;
|
else if (id == ID_NOTES) return notes->canPaste();
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
void CardsPanel::doPaste() {
|
void CardsPanel::doPaste() {
|
||||||
if (card_list->canPaste()) {
|
if (card_list->canPaste()) {
|
||||||
card_list->doPaste();
|
card_list->doPaste();
|
||||||
} else {
|
} else {
|
||||||
int id = focused_control(this);
|
int id = focused_control(this);
|
||||||
if (id == ID_EDITOR) editor->doPaste();
|
if (id == ID_EDITOR) editor->doPaste();
|
||||||
else if (id == ID_NOTES) notes->doPaste();
|
else if (id == ID_CARD_LINK_EDITOR) link_editor->doPaste();
|
||||||
|
else if (id == ID_NOTES) notes->doPaste();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +564,7 @@ public:
|
|||||||
SearchFindInfo(CardsPanel& panel, wxFindReplaceData& what) : FindInfo(what), panel(panel) {}
|
SearchFindInfo(CardsPanel& panel, wxFindReplaceData& what) : FindInfo(what), panel(panel) {}
|
||||||
bool handle(const CardP& card, const TextValueP& value, size_t pos, bool was_selection) override {
|
bool handle(const CardP& card, const TextValueP& value, size_t pos, bool was_selection) override {
|
||||||
// Select the card
|
// Select the card
|
||||||
panel.card_list->setCard(card);
|
panel.setCard(card, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@@ -477,7 +576,7 @@ public:
|
|||||||
ReplaceFindInfo(CardsPanel& panel, wxFindReplaceData& what) : FindInfo(what), panel(panel) {}
|
ReplaceFindInfo(CardsPanel& panel, wxFindReplaceData& what) : FindInfo(what), panel(panel) {}
|
||||||
bool handle(const CardP& card, const TextValueP& value, size_t pos, bool was_selection) override {
|
bool handle(const CardP& card, const TextValueP& value, size_t pos, bool was_selection) override {
|
||||||
// Select the card
|
// Select the card
|
||||||
panel.card_list->setCard(card);
|
panel.setCard(card, true);
|
||||||
// Replace
|
// Replace
|
||||||
if (was_selection) {
|
if (was_selection) {
|
||||||
panel.editor->insert(escape(what.GetReplaceString()), _("Replace"));
|
panel.editor->insert(escape(what.GetReplaceString()), _("Replace"));
|
||||||
@@ -512,10 +611,12 @@ bool CardsPanel::search(FindInfo& find, bool from_start) {
|
|||||||
if (include) {
|
if (include) {
|
||||||
editor->setCard(card);
|
editor->setCard(card);
|
||||||
if (editor->search(find, from_start || card != current)) {
|
if (editor->search(find, from_start || card != current)) {
|
||||||
return true; // done
|
// found a card, call handle
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// didn't find anything, put editor back in its previous state
|
||||||
editor->setCard(current);
|
editor->setCard(current);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -527,9 +628,76 @@ CardP CardsPanel::selectedCard() const {
|
|||||||
}
|
}
|
||||||
void CardsPanel::selectCard(const CardP& card) {
|
void CardsPanel::selectCard(const CardP& card) {
|
||||||
if (!set) return; // we want onChangeSet first
|
if (!set) return; // we want onChangeSet first
|
||||||
|
|
||||||
card_list->setCard(card);
|
card_list->setCard(card);
|
||||||
|
|
||||||
editor->setCard(card);
|
editor->setCard(card);
|
||||||
|
vector<pair<CardP, String>> linked_cards = card->getLinkedCards(*set);
|
||||||
|
int count = linked_cards.size();
|
||||||
|
if (count >= 1) {
|
||||||
|
link_box_1->Show(true);
|
||||||
|
link_editor->setCard(linked_cards[0].first);
|
||||||
|
link_viewer_1->setCard(linked_cards[0].first);
|
||||||
|
link_relation_1->SetLabel(linked_cards[0].second);
|
||||||
|
if (count == 1) {
|
||||||
|
link_editor->Show(true);
|
||||||
|
link_viewer_1->Show(false);
|
||||||
|
link_select->Show(true);
|
||||||
|
link_editor->InvalidateBestSize();
|
||||||
|
link_relation_1->SetMaxSize(wxSize(link_editor->GetSize().x - link_unlink_1->GetSize().x, -1));
|
||||||
|
} else {
|
||||||
|
link_editor->Show(false);
|
||||||
|
link_viewer_1->Show(true);
|
||||||
|
link_select->Show(false);
|
||||||
|
link_viewer_1->InvalidateBestSize();
|
||||||
|
link_relation_1->SetMaxSize(wxSize(link_viewer_1->GetSize().x - link_unlink_1->GetSize().x, -1));
|
||||||
|
}
|
||||||
|
link_relation_1->InvalidateBestSize();
|
||||||
|
} else {
|
||||||
|
link_box_1->Show(false);
|
||||||
|
link_editor->setCard(card);
|
||||||
|
link_viewer_1->setCard(card);
|
||||||
|
//link_relation_1->SetLabel(wxEmptyString);
|
||||||
|
}
|
||||||
|
if (count >= 2) {
|
||||||
|
link_box_2->Show(true);
|
||||||
|
link_viewer_2->setCard(linked_cards[1].first);
|
||||||
|
link_relation_2->SetLabel(linked_cards[1].second);
|
||||||
|
link_relation_2->SetMaxSize(wxSize(link_viewer_2->GetSize().x - link_unlink_2->GetSize().x, -1));
|
||||||
|
link_relation_2->InvalidateBestSize();
|
||||||
|
} else {
|
||||||
|
link_box_2->Show(false);
|
||||||
|
link_viewer_2->setCard(card);
|
||||||
|
//link_relation_2->SetLabel(wxEmptyString);
|
||||||
|
}
|
||||||
|
if (count >= 3) {
|
||||||
|
link_box_3->Show(true);
|
||||||
|
link_viewer_3->setCard(linked_cards[2].first);
|
||||||
|
link_relation_3->SetLabel(linked_cards[2].second);
|
||||||
|
link_relation_3->SetMaxSize(wxSize(link_viewer_3->GetSize().x - link_unlink_3->GetSize().x, -1));
|
||||||
|
link_relation_3->InvalidateBestSize();
|
||||||
|
} else {
|
||||||
|
link_box_3->Show(false);
|
||||||
|
link_viewer_3->setCard(card);
|
||||||
|
//link_relation_3->SetLabel(wxEmptyString);
|
||||||
|
}
|
||||||
|
if (count >= 4) {
|
||||||
|
link_box_4->Show(true);
|
||||||
|
link_viewer_4->setCard(linked_cards[3].first);
|
||||||
|
link_relation_4->SetLabel(linked_cards[3].second);
|
||||||
|
link_relation_4->SetMaxSize(wxSize(link_viewer_4->GetSize().x - link_unlink_4->GetSize().x, -1));
|
||||||
|
link_relation_4->InvalidateBestSize();
|
||||||
|
} else {
|
||||||
|
link_box_4->Show(false);
|
||||||
|
link_viewer_4->setCard(card);
|
||||||
|
//link_relation_4->SetLabel(wxEmptyString);
|
||||||
|
}
|
||||||
|
if (count >= 5) {
|
||||||
|
queue_message(MESSAGE_WARNING, "DEBUG More than 4 linked cards found for card: " + card->identification());
|
||||||
|
}
|
||||||
|
|
||||||
notes->setValue(card ? &card->notes : nullptr);
|
notes->setValue(card ? &card->notes : nullptr);
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
updateNotesPosition();
|
updateNotesPosition();
|
||||||
}
|
}
|
||||||
@@ -539,6 +707,20 @@ void CardsPanel::selectFirstCard() {
|
|||||||
card_list->selectFirst();
|
card_list->selectFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardsPanel::setCard(const CardP& card, bool event) {
|
||||||
|
if (!set) return; // we want onChangeSet first
|
||||||
|
card_list->setCard(card, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardsPanel::refreshCard(const CardP& card) {
|
||||||
|
if (!set) return; // we want onChangeSet first
|
||||||
|
card_list->RefreshItem(card_list->findGivenItemPos(card));
|
||||||
|
}
|
||||||
|
|
||||||
void CardsPanel::getCardLists(vector<CardListBase*>& out) {
|
void CardsPanel::getCardLists(vector<CardListBase*>& out) {
|
||||||
out.push_back(card_list);
|
out.push_back(card_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardsPanel::setFocusedEditor(DataEditor* editor) {
|
||||||
|
focused_editor = editor;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ class wxSplitterWindow;
|
|||||||
class FilteredImageCardList;
|
class FilteredImageCardList;
|
||||||
class DataEditor;
|
class DataEditor;
|
||||||
class TextCtrl;
|
class TextCtrl;
|
||||||
|
class CardViewer;
|
||||||
|
class wxSizer;
|
||||||
|
class wxButton;
|
||||||
class HoverButton;
|
class HoverButton;
|
||||||
class FindInfo;
|
class FindInfo;
|
||||||
class FilterCtrl;
|
class FilterCtrl;
|
||||||
@@ -74,17 +77,25 @@ public:
|
|||||||
CardP selectedCard() const override;
|
CardP selectedCard() const override;
|
||||||
void selectCard(const CardP& card) override;
|
void selectCard(const CardP& card) override;
|
||||||
void selectFirstCard() override;
|
void selectFirstCard() override;
|
||||||
|
void setCard(const CardP& card, bool event = false);
|
||||||
|
void refreshCard(const CardP& card);
|
||||||
|
|
||||||
void getCardLists(vector<CardListBase*>& out) override;
|
void getCardLists(vector<CardListBase*>& out) override;
|
||||||
|
|
||||||
|
void setFocusedEditor(DataEditor* editor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --------------------------------------------------- : Controls
|
// --------------------------------------------------- : Controls
|
||||||
wxSizer* s_left;
|
wxSizer* s_left;
|
||||||
wxSplitterWindow* splitter;
|
wxSplitterWindow* splitter;
|
||||||
DataEditor* editor;
|
DataEditor* editor, *link_editor, *focused_editor;
|
||||||
FilteredImageCardList* card_list;
|
FilteredImageCardList* card_list;
|
||||||
wxPanel* nodes_panel;
|
wxPanel* nodes_panel;
|
||||||
TextCtrl* notes;
|
TextCtrl* notes;
|
||||||
|
wxSizer* link_box_1, *link_box_2, *link_box_3, *link_box_4;
|
||||||
|
wxStaticText* link_relation_1, *link_relation_2, *link_relation_3, *link_relation_4;
|
||||||
|
CardViewer* link_viewer_1, *link_viewer_2, *link_viewer_3, *link_viewer_4;
|
||||||
|
wxButton* link_unlink_1, *link_unlink_2, *link_unlink_3, *link_unlink_4, *link_select;
|
||||||
HoverButton* collapse_notes;
|
HoverButton* collapse_notes;
|
||||||
FilterCtrl* filter;
|
FilterCtrl* filter;
|
||||||
String filter_value; // value of filter, need separate variable because the control is destroyed
|
String filter_value; // value of filter, need separate variable because the control is destroyed
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ DECLARE_POINTER_TYPE(ConsoleMessage);
|
|||||||
class ConsoleMessage : public IntrusivePtrBase<ConsoleMessage> {
|
class ConsoleMessage : public IntrusivePtrBase<ConsoleMessage> {
|
||||||
public:
|
public:
|
||||||
MessageType type;
|
MessageType type;
|
||||||
String text; // string message
|
String text; // string message
|
||||||
wxDateTime timestamp;
|
wxDateTime timestamp;
|
||||||
Bitmap bitmap; // image message instead of string
|
Bitmap bitmap; // image message instead of string
|
||||||
ScriptValueP value; // other valued message (images? cards?)
|
ScriptValueP value; // other valued message (images? cards?)
|
||||||
@@ -80,13 +80,13 @@ public:
|
|||||||
}
|
}
|
||||||
void add_message(MessageType type, String const& text, bool joined_to_previous = false) {
|
void add_message(MessageType type, String const& text, bool joined_to_previous = false) {
|
||||||
add_message(make_intrusive<ConsoleMessage>(type,text,joined_to_previous));
|
add_message(make_intrusive<ConsoleMessage>(type,text,joined_to_previous));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_console() {
|
void clear_console() {
|
||||||
messages.clear();
|
messages.clear();
|
||||||
layout_all();
|
layout_all();
|
||||||
selection = messages.size();
|
selection = messages.size();
|
||||||
update_scrollbar();
|
update_scrollbar();
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,11 +245,11 @@ private:
|
|||||||
wxAutoBufferedPaintDC dc(this);
|
wxAutoBufferedPaintDC dc(this);
|
||||||
PrepareDC(dc);
|
PrepareDC(dc);
|
||||||
draw(dc);
|
draw(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(wxDC& dc) const {
|
void draw(wxDC& dc) const {
|
||||||
clearDC(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
clearDC(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||||
dc.SetFont(*wxNORMAL_FONT);
|
dc.SetFont(*wxNORMAL_FONT);
|
||||||
|
|
||||||
FOR_EACH_CONST(msg, messages) {
|
FOR_EACH_CONST(msg, messages) {
|
||||||
draw(dc, *msg);
|
draw(dc, *msg);
|
||||||
@@ -283,23 +283,23 @@ private:
|
|||||||
// draw background
|
// draw background
|
||||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||||
dc.SetBrush(lerp(bg,color, 0.05));
|
dc.SetBrush(lerp(bg,color, 0.05));
|
||||||
dc.DrawRectangle(left,top,width,msg.height);
|
dc.DrawRectangle(left,top,width,msg.height);
|
||||||
|
|
||||||
// draw foreground
|
// draw foreground
|
||||||
dc.SetTextForeground(fg);
|
dc.SetTextForeground(fg);
|
||||||
|
|
||||||
// draw timestamp
|
// draw timestamp
|
||||||
dc.DrawText(msg.timestamp.FormatISOTime(), left + TIMESTAMP_PADDING, top + TEXT_PADDING_TOP);
|
dc.DrawText(msg.timestamp.FormatISOTime(), left + TIMESTAMP_PADDING, top + TEXT_PADDING_TOP);
|
||||||
|
|
||||||
int timestamp_resolved_width;
|
int timestamp_resolved_width;
|
||||||
dc.GetTextExtent(_("55:55:55"), ×tamp_resolved_width, nullptr);
|
dc.GetTextExtent(_("55:55:55"), ×tamp_resolved_width, nullptr);
|
||||||
|
|
||||||
left += timestamp_resolved_width;
|
left += timestamp_resolved_width;
|
||||||
left += TIMESTAMP_PADDING * 2;
|
left += TIMESTAMP_PADDING * 2;
|
||||||
|
|
||||||
// draw line right of timestamp
|
// draw line right of timestamp
|
||||||
dc.SetPen(lerp(bg, fg, 0.3));
|
dc.SetPen(lerp(bg, fg, 0.3));
|
||||||
dc.DrawLine(left, top, left, top + msg.height);
|
dc.DrawLine(left, top, left, top + msg.height);
|
||||||
|
|
||||||
// draw icon
|
// draw icon
|
||||||
if (icons[msg.type].Ok()) {
|
if (icons[msg.type].Ok()) {
|
||||||
@@ -331,7 +331,7 @@ private:
|
|||||||
if (msg.bitmap.Ok()) {
|
if (msg.bitmap.Ok()) {
|
||||||
dc.DrawBitmap(msg.bitmap, text_left, text_top);
|
dc.DrawBitmap(msg.bitmap, text_left, text_top);
|
||||||
text_top += msg.bitmap.GetHeight();
|
text_top += msg.bitmap.GetHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw line below item
|
// draw line below item
|
||||||
dc.SetPen(lerp(bg,fg, 0.3));
|
dc.SetPen(lerp(bg,fg, 0.3));
|
||||||
@@ -356,9 +356,9 @@ private:
|
|||||||
}
|
}
|
||||||
if (begin != msg.text.end()) {
|
if (begin != msg.text.end()) {
|
||||||
text_height += dc.GetCharHeight() + TEXT_LINE_SPACING;
|
text_height += dc.GetCharHeight() + TEXT_LINE_SPACING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// account for the height of a timestamp even if there is no other text content.
|
// account for the height of a timestamp even if there is no other text content.
|
||||||
if (text_height == 0) {
|
if (text_height == 0) {
|
||||||
text_height = dc.GetCharHeight() + TEXT_LINE_SPACING;
|
text_height = dc.GetCharHeight() + TEXT_LINE_SPACING;
|
||||||
}
|
}
|
||||||
@@ -371,9 +371,9 @@ private:
|
|||||||
|
|
||||||
// --------------------------------------------------- : Layout
|
// --------------------------------------------------- : Layout
|
||||||
|
|
||||||
static constexpr int LIST_SPACING = 1;
|
static constexpr int LIST_SPACING = 1;
|
||||||
static constexpr int TIMESTAMP_PADDING = 3;
|
static constexpr int TIMESTAMP_PADDING = 3;
|
||||||
static constexpr int ICON_PADDING = 3;
|
static constexpr int ICON_PADDING = 3;
|
||||||
static constexpr int ICON_PADDING_LEFT = TIMESTAMP_PADDING + 3;
|
static constexpr int ICON_PADDING_LEFT = TIMESTAMP_PADDING + 3;
|
||||||
static constexpr int TEXT_PADDING_LEFT = ICON_PADDING_LEFT + 16 + 4;
|
static constexpr int TEXT_PADDING_LEFT = ICON_PADDING_LEFT + 16 + 4;
|
||||||
static constexpr int TEXT_PADDING_RIGHT = 4;
|
static constexpr int TEXT_PADDING_RIGHT = 4;
|
||||||
@@ -488,7 +488,7 @@ END_EVENT_TABLE()
|
|||||||
|
|
||||||
ConsolePanel::ConsolePanel(Window* parent, int id)
|
ConsolePanel::ConsolePanel(Window* parent, int id)
|
||||||
: SetWindowPanel(parent, id)
|
: SetWindowPanel(parent, id)
|
||||||
, menuConsole(nullptr)
|
, menuConsole(nullptr)
|
||||||
, messages(nullptr)
|
, messages(nullptr)
|
||||||
, entry(nullptr)
|
, entry(nullptr)
|
||||||
, is_active_window(false)
|
, is_active_window(false)
|
||||||
@@ -514,13 +514,13 @@ ConsolePanel::ConsolePanel(Window* parent, int id)
|
|||||||
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||||
s->Add(splitter, 1, wxEXPAND);
|
s->Add(splitter, 1, wxEXPAND);
|
||||||
s->SetSizeHints(this);
|
s->SetSizeHints(this);
|
||||||
SetSizer(s);
|
SetSizer(s);
|
||||||
|
|
||||||
// init menus
|
// init menus
|
||||||
menuConsole = new wxMenu();
|
menuConsole = new wxMenu();
|
||||||
add_menu_item_tr(menuConsole, ID_CLEAR_CONSOLE, "clear_console", "clear console");
|
add_menu_item_tr(menuConsole, ID_CLEAR_CONSOLE, "clear_console", "clear console");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsolePanel::~ConsolePanel() {
|
ConsolePanel::~ConsolePanel() {
|
||||||
delete menuConsole;
|
delete menuConsole;
|
||||||
}
|
}
|
||||||
@@ -542,19 +542,19 @@ void ConsolePanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
|
|
||||||
// stop blinker
|
// stop blinker
|
||||||
is_active_window = true;
|
is_active_window = true;
|
||||||
stop_blinker();
|
stop_blinker();
|
||||||
|
|
||||||
add_tool_tr(tb, ID_CLEAR_CONSOLE, "clear_console", "clear console");
|
add_tool_tr(tb, ID_CLEAR_CONSOLE, "clear_console", "clear console");
|
||||||
tb->Realize();
|
tb->Realize();
|
||||||
|
|
||||||
mb->Insert(2, menuConsole, _MENU_("console"));
|
mb->Insert(2, menuConsole, _MENU_("console"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsolePanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
void ConsolePanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||||
// Toolbar
|
// Toolbar
|
||||||
tb->DeleteTool(ID_CLEAR_CONSOLE);
|
tb->DeleteTool(ID_CLEAR_CONSOLE);
|
||||||
// Menus
|
// Menus
|
||||||
mb->Remove(2);
|
mb->Remove(2);
|
||||||
|
|
||||||
// we are no longer active, allow blinker
|
// we are no longer active, allow blinker
|
||||||
is_active_window = false;
|
is_active_window = false;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class HistoryTextCtrl;
|
|||||||
|
|
||||||
class ConsolePanel : public SetWindowPanel {
|
class ConsolePanel : public SetWindowPanel {
|
||||||
public:
|
public:
|
||||||
ConsolePanel(Window* parent, int id);
|
ConsolePanel(Window* parent, int id);
|
||||||
~ConsolePanel();
|
~ConsolePanel();
|
||||||
|
|
||||||
// --------------------------------------------------- : UI
|
// --------------------------------------------------- : UI
|
||||||
@@ -49,8 +49,8 @@ private:
|
|||||||
wxSplitterWindow* splitter;
|
wxSplitterWindow* splitter;
|
||||||
MessageCtrl* messages;
|
MessageCtrl* messages;
|
||||||
wxPanel* entry_panel;
|
wxPanel* entry_panel;
|
||||||
HistoryTextCtrl* entry;
|
HistoryTextCtrl* entry;
|
||||||
|
|
||||||
wxMenu* menuConsole;
|
wxMenu* menuConsole;
|
||||||
|
|
||||||
void get_pending_errors();
|
void get_pending_errors();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ void SetInfoPanel::onChangeSet() {
|
|||||||
void SetInfoPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
void SetInfoPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||||
// Toolbar
|
// Toolbar
|
||||||
add_tool_tr(tb, ID_FORMAT_BOLD, "bold", "bold", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_BOLD, "bold", "bold", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_ITALIC, "italic", "italic", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_ITALIC, "italic", "italic", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_UNDERLINE, "underline", "underline", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_UNDERLINE, "underline", "underline", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_SYMBOL, "symbol", "symbols", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_SYMBOL, "symbol", "symbols", false, wxITEM_CHECK);
|
||||||
add_tool_tr(tb, ID_FORMAT_REMINDER, "reminder", "reminder_text", false, wxITEM_CHECK);
|
add_tool_tr(tb, ID_FORMAT_REMINDER, "reminder", "reminder_text", false, wxITEM_CHECK);
|
||||||
@@ -43,7 +43,7 @@ void SetInfoPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
// Menus
|
// Menus
|
||||||
auto menuFormat = new wxMenu();
|
auto menuFormat = new wxMenu();
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_BOLD, "bold", "bold", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_BOLD, "bold", "bold", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_ITALIC, "italic", "italic", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_ITALIC, "italic", "italic", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_UNDERLINE, "underline", "underline", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_UNDERLINE, "underline", "underline", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_SYMBOL, "symbol", "symbols", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_SYMBOL, "symbol", "symbols", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuFormat, ID_FORMAT_REMINDER, "reminder", "reminder_text", wxITEM_CHECK);
|
add_menu_item_tr(menuFormat, ID_FORMAT_REMINDER, "reminder", "reminder_text", wxITEM_CHECK);
|
||||||
@@ -55,7 +55,7 @@ void SetInfoPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
void SetInfoPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
void SetInfoPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||||
// Toolbar
|
// Toolbar
|
||||||
tb->DeleteTool(ID_FORMAT_BOLD);
|
tb->DeleteTool(ID_FORMAT_BOLD);
|
||||||
tb->DeleteTool(ID_FORMAT_ITALIC);
|
tb->DeleteTool(ID_FORMAT_ITALIC);
|
||||||
tb->DeleteTool(ID_FORMAT_UNDERLINE);
|
tb->DeleteTool(ID_FORMAT_UNDERLINE);
|
||||||
tb->DeleteTool(ID_FORMAT_SYMBOL);
|
tb->DeleteTool(ID_FORMAT_SYMBOL);
|
||||||
tb->DeleteTool(ID_FORMAT_REMINDER);
|
tb->DeleteTool(ID_FORMAT_REMINDER);
|
||||||
|
|||||||
+14
-14
@@ -35,20 +35,20 @@ void StylePanel::initControls() {
|
|||||||
list = new PackageList (this, wxID_ANY);
|
list = new PackageList (this, wxID_ANY);
|
||||||
use_for_all = new wxButton (this, ID_STYLE_USE_FOR_ALL, _BUTTON_("use for all cards"));
|
use_for_all = new wxButton (this, ID_STYLE_USE_FOR_ALL, _BUTTON_("use for all cards"));
|
||||||
use_custom_options = new wxCheckBox(this, ID_STYLE_USE_CUSTOM, _BUTTON_("use custom styling options"));
|
use_custom_options = new wxCheckBox(this, ID_STYLE_USE_CUSTOM, _BUTTON_("use custom styling options"));
|
||||||
editor = new StylingEditor(this, ID_EDITOR, wxNO_BORDER);
|
editor = new StylingEditor(this, ID_EDITOR, wxNO_BORDER);
|
||||||
|
|
||||||
stylesheet_filter = new FilterCtrl(this, ID_STYLESHEET_FILTER, _LABEL_("search stylesheet list"), _HELP_("search stylesheet list control"));
|
stylesheet_filter = new FilterCtrl(this, ID_STYLESHEET_FILTER, _LABEL_("search stylesheet list"), _HELP_("search stylesheet list control"));
|
||||||
stylesheet_filter->setFilter(stylesheet_filter_value);
|
stylesheet_filter->setFilter(stylesheet_filter_value);
|
||||||
|
|
||||||
// init sizer
|
// init sizer
|
||||||
wxSizer* s = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer* s = new wxBoxSizer(wxHORIZONTAL);
|
||||||
s->Add(preview, 0, wxRIGHT, 2);
|
s->Add(preview, 0, wxRIGHT, 2);
|
||||||
wxSizer* s2 = new wxBoxSizer(wxVERTICAL);
|
wxSizer* s2 = new wxBoxSizer(wxVERTICAL);
|
||||||
s2->Add(list, 0, wxEXPAND | wxBOTTOM, 4);
|
s2->Add(list, 0, wxEXPAND | wxBOTTOM, 4);
|
||||||
wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL);
|
||||||
s3->Add(stylesheet_filter, 0, wxBOTTOM | wxLEFT, 4);
|
s3->Add(stylesheet_filter, 0, wxBOTTOM | wxLEFT, 4);
|
||||||
s3->AddStretchSpacer();
|
s3->AddStretchSpacer();
|
||||||
s3->Add(use_for_all, 0, wxBOTTOM | wxRIGHT, 4);
|
s3->Add(use_for_all, 0, wxBOTTOM | wxRIGHT, 4);
|
||||||
s2->Add(s3, wxSizerFlags().Expand().Border(wxALL, 6));
|
s2->Add(s3, wxSizerFlags().Expand().Border(wxALL, 6));
|
||||||
wxSizer* s4 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("styling options"));
|
wxSizer* s4 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("styling options"));
|
||||||
s4->Add(use_custom_options, 0, wxEXPAND | wxALL, 4);
|
s4->Add(use_custom_options, 0, wxEXPAND | wxALL, 4);
|
||||||
@@ -81,10 +81,10 @@ void StylePanel::updateListSize() {
|
|||||||
if (column_count != list->column_count) {
|
if (column_count != list->column_count) {
|
||||||
list->column_count = column_count;
|
list->column_count = column_count;
|
||||||
static_cast<SetWindow*>(GetParent())->fixMinWindowSize();
|
static_cast<SetWindow*>(GetParent())->fixMinWindowSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
list_size_already_initialized = true;
|
list_size_already_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StylePanel::Layout() {
|
bool StylePanel::Layout() {
|
||||||
updateListSize();
|
updateListSize();
|
||||||
@@ -136,8 +136,8 @@ void StylePanel::onAction(const Action& action, bool undone) {
|
|||||||
use_for_all->Enable(card && card->stylesheet);
|
use_for_all->Enable(card && card->stylesheet);
|
||||||
use_custom_options->Enable((bool)card);
|
use_custom_options->Enable((bool)card);
|
||||||
use_custom_options->SetValue(card ? card->has_styling : false);
|
use_custom_options->SetValue(card ? card->has_styling : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StylePanel::onStylesheetFilterUpdate(wxCommandEvent&) {
|
void StylePanel::onStylesheetFilterUpdate(wxCommandEvent&) {
|
||||||
if (list->hasSelection()) {
|
if (list->hasSelection()) {
|
||||||
StyleSheetP existingStylesheetSelection = list->getSelection<StyleSheet>(false);
|
StyleSheetP existingStylesheetSelection = list->getSelection<StyleSheet>(false);
|
||||||
@@ -208,7 +208,7 @@ void StylePanel::onUseCustom(wxCommandEvent&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(StylePanel, wxPanel)
|
BEGIN_EVENT_TABLE(StylePanel, wxPanel)
|
||||||
EVT_GALLERY_SELECT(wxID_ANY, StylePanel::onStyleSelect)
|
EVT_GALLERY_SELECT(wxID_ANY, StylePanel::onStyleSelect)
|
||||||
EVT_COMMAND_RANGE(ID_STYLESHEET_FILTER, ID_STYLESHEET_FILTER, wxEVT_COMMAND_TEXT_UPDATED, StylePanel::onStylesheetFilterUpdate)
|
EVT_COMMAND_RANGE(ID_STYLESHEET_FILTER, ID_STYLESHEET_FILTER, wxEVT_COMMAND_TEXT_UPDATED, StylePanel::onStylesheetFilterUpdate)
|
||||||
EVT_BUTTON (ID_STYLE_USE_FOR_ALL, StylePanel::onUseForAll)
|
EVT_BUTTON (ID_STYLE_USE_FOR_ALL, StylePanel::onUseForAll)
|
||||||
EVT_CHECKBOX (ID_STYLE_USE_CUSTOM, StylePanel::onUseCustom)
|
EVT_CHECKBOX (ID_STYLE_USE_CUSTOM, StylePanel::onUseCustom)
|
||||||
|
|||||||
@@ -266,8 +266,8 @@ void SymbolPartList::onChar(wxKeyEvent& ev) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// See gui/value/text.cpp
|
// See gui/value/text.cpp
|
||||||
#if defined UNICODE
|
#if defined UNICODE
|
||||||
if (ev.GetUnicodeKey() >= WXK_SPACE) {
|
if (ev.GetUnicodeKey() >= WXK_SPACE) {
|
||||||
#elif defined __WXMSW__
|
#elif defined __WXMSW__
|
||||||
if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) {
|
if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) {
|
||||||
|
|||||||
+25
-10
@@ -11,6 +11,7 @@
|
|||||||
#include <gui/image_slice_window.hpp>
|
#include <gui/image_slice_window.hpp>
|
||||||
#include <data/format/clipboard.hpp>
|
#include <data/format/clipboard.hpp>
|
||||||
#include <data/action/value.hpp>
|
#include <data/action/value.hpp>
|
||||||
|
#include <data/card.hpp>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
#include <gui/util.hpp>
|
#include <gui/util.hpp>
|
||||||
|
|
||||||
@@ -19,7 +20,19 @@
|
|||||||
IMPLEMENT_VALUE_EDITOR(Image) {}
|
IMPLEMENT_VALUE_EDITOR(Image) {}
|
||||||
|
|
||||||
bool ImageValueEditor::onLeftDClick(const RealPoint&, wxMouseEvent&) {
|
bool ImageValueEditor::onLeftDClick(const RealPoint&, wxMouseEvent&) {
|
||||||
String filename = wxFileSelector(_("Open image file"), settings.default_image_dir, _(""), _(""),
|
String directory = settings.default_image_dir;
|
||||||
|
String filename = _("");
|
||||||
|
CardP card = parent.getCard();
|
||||||
|
String cardname = card ? card->identification() : _("clipboard");
|
||||||
|
if (ImageSliceWindow::previously_used_settings_path.find(cardname) != ImageSliceWindow::previously_used_settings_path.end()) {
|
||||||
|
String filepath = ImageSliceWindow::previously_used_settings_path[cardname];
|
||||||
|
size_t pos = filepath.rfind(wxFileName::GetPathSeparator());
|
||||||
|
if (pos != String::npos) {
|
||||||
|
directory = filepath.substr(0, pos+1);
|
||||||
|
filename = filepath.substr(pos+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filename = wxFileSelector(_("Open image file"), directory, filename, _(""),
|
||||||
_("All images|*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff|Windows bitmaps (*.bmp)|*.bmp|JPEG images (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG images (*.png)|*.png|GIF images (*.gif)|*.gif|TIFF images (*.tif;*.tiff)|*.tif;*.tiff"),
|
_("All images|*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff|Windows bitmaps (*.bmp)|*.bmp|JPEG images (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG images (*.png)|*.png|GIF images (*.gif)|*.gif|TIFF images (*.tif;*.tiff)|*.tif;*.tiff"),
|
||||||
wxFD_OPEN, wxGetTopLevelParent(&editor()));
|
wxFD_OPEN, wxGetTopLevelParent(&editor()));
|
||||||
if (!filename.empty()) {
|
if (!filename.empty()) {
|
||||||
@@ -29,28 +42,28 @@ bool ImageValueEditor::onLeftDClick(const RealPoint&, wxMouseEvent&) {
|
|||||||
wxLogNull noLog;
|
wxLogNull noLog;
|
||||||
image = wxImage(filename);
|
image = wxImage(filename);
|
||||||
}
|
}
|
||||||
sliceImage(image);
|
sliceImage(image, filename, cardname);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageValueEditor::sliceImage(const Image& image) {
|
void ImageValueEditor::sliceImage(const Image& image, const String& filename, const String& cardname) {
|
||||||
if (!image.Ok()) return;
|
if (!image.Ok()) return;
|
||||||
// mask
|
// mask
|
||||||
GeneratedImage::Options options((int)style().width, (int)style().height, &parent.getStylePackage(), &parent.getLocalPackage());
|
GeneratedImage::Options options((int)style().width, (int)style().height, &parent.getStylePackage(), &parent.getLocalPackage());
|
||||||
AlphaMask mask;
|
AlphaMask mask;
|
||||||
style().mask.getNoCache(options,mask);
|
style().mask.getNoCache(options,mask);
|
||||||
// slice
|
// slice
|
||||||
ImageSliceWindow s(wxGetTopLevelParent(&editor()), image, style().getSize(), mask);
|
ImageSliceWindow s(wxGetTopLevelParent(&editor()), image, filename, cardname, style().getSize(), mask);
|
||||||
// clicked ok?
|
// clicked ok?
|
||||||
if (s.ShowModal() == wxID_OK) {
|
if (s.ShowModal() == wxID_OK) {
|
||||||
// store the image into the set
|
// store the image into the set
|
||||||
LocalFileName new_image_file = getLocalPackage().newFileName(field().name, settings.internal_image_extension ? _(".png") : _("")); // a new unique name in the package
|
LocalFileName new_image_file = getLocalPackage().newFileName(field().name, settings.internal_image_extension ? _(".png") : _("")); // a new unique name in the package
|
||||||
|
|
||||||
// Specify a desired size based on the stylesheet and a scale multiplier defined within the user's settings.
|
// Specify a desired size based on the stylesheet and a scale multiplier defined within the user's settings.
|
||||||
// Storing at a greater than 100% resolution allows for better exports >100%, but may change how images look when filters (sharpen) are applied.
|
// Storing at a greater than 100% resolution allows for better exports >100%, but may change how images look when filters (sharpen) are applied.
|
||||||
// It also disrupts some of the patterns in use for doing popout planeswalkers since you have to do the math at both scales.
|
// It also disrupts some of the patterns in use for doing popout planeswalkers since you have to do the math at both scales.
|
||||||
// Additionally, this bloats the set file size as even under-resolution images are upscaled to the new minimum size.
|
// Additionally, this bloats the set file size as even under-resolution images are upscaled to the new minimum size.
|
||||||
Image img = s.getImage(settings.internal_scale);
|
Image img = s.getImage(settings.internal_scale);
|
||||||
img.SaveFile(getLocalPackage().nameOut(new_image_file), wxBITMAP_TYPE_PNG); // always use PNG images, see #69. Disk space is cheap anyway.
|
img.SaveFile(getLocalPackage().nameOut(new_image_file), wxBITMAP_TYPE_PNG); // always use PNG images, see #69. Disk space is cheap anyway.
|
||||||
addAction(value_action(valueP(), new_image_file));
|
addAction(value_action(valueP(), new_image_file));
|
||||||
@@ -88,7 +101,9 @@ bool ImageValueEditor::doPaste() {
|
|||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
if (!ok) return false;
|
if (!ok) return false;
|
||||||
// slice
|
// slice
|
||||||
sliceImage(data.GetBitmap().ConvertToImage());
|
CardP card = parent.getCard();
|
||||||
|
String cardname = card ? card->identification() : _("clipboard");
|
||||||
|
sliceImage(data.GetBitmap().ConvertToImage(), _("clipboard"), cardname);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
bool onChar(wxKeyEvent&) override;
|
bool onChar(wxKeyEvent&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Open the image slice window showing the give image
|
// Open the image slice window showing the given image
|
||||||
void sliceImage(const Image&);
|
void sliceImage(const Image&, const String& filename, const String& cardname);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -482,13 +482,13 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
#if defined UNICODE
|
#if defined UNICODE
|
||||||
// I think in theory this works because the UnicodeKey is intended to be only character values.
|
// I think in theory this works because the UnicodeKey is intended to be only character values.
|
||||||
// See the following link for pretty much an exact example of this type of handling.
|
// See the following link for pretty much an exact example of this type of handling.
|
||||||
// https://docs.wxwidgets.org/3.0/classwx_key_event.html#a3dccc5a254770931e5d8066ef47e7fb0
|
// https://docs.wxwidgets.org/3.0/classwx_key_event.html#a3dccc5a254770931e5d8066ef47e7fb0
|
||||||
// Most of the special keys (<32) are handled in the case structure above anyways.
|
// Most of the special keys (<32) are handled in the case structure above anyways.
|
||||||
// I tried to replicate the Numpad issue mentioned below, but couldn't - so unclear if that's still relevant.
|
// I tried to replicate the Numpad issue mentioned below, but couldn't - so unclear if that's still relevant.
|
||||||
if (ev.GetUnicodeKey() >= WXK_SPACE) {
|
if (ev.GetUnicodeKey() >= WXK_SPACE) {
|
||||||
#elif defined __WXMSW__
|
#elif defined __WXMSW__
|
||||||
if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) {
|
if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) {
|
||||||
@@ -822,7 +822,7 @@ bool TextValueEditor::hasFormat(int type) const {
|
|||||||
case ID_FORMAT_BOLD:
|
case ID_FORMAT_BOLD:
|
||||||
return is_in_tag(value().value(), _("<b"), selection_start_i, selection_end_i);
|
return is_in_tag(value().value(), _("<b"), selection_start_i, selection_end_i);
|
||||||
case ID_FORMAT_ITALIC:
|
case ID_FORMAT_ITALIC:
|
||||||
return is_in_tag(value().value(), _("<i"), selection_start_i, selection_end_i);
|
return is_in_tag(value().value(), _("<i"), selection_start_i, selection_end_i);
|
||||||
case ID_FORMAT_UNDERLINE:
|
case ID_FORMAT_UNDERLINE:
|
||||||
return is_in_tag(value().value(), _("<u"), selection_start_i, selection_end_i);
|
return is_in_tag(value().value(), _("<u"), selection_start_i, selection_end_i);
|
||||||
case ID_FORMAT_SYMBOL:
|
case ID_FORMAT_SYMBOL:
|
||||||
@@ -850,7 +850,7 @@ void TextValueEditor::doFormat(int type) {
|
|||||||
case ID_FORMAT_ITALIC: {
|
case ID_FORMAT_ITALIC: {
|
||||||
addAction(toggle_format_action(valueP(), _("i"), selection_start_i, selection_end_i, selection_start, selection_end, _("Italic")));
|
addAction(toggle_format_action(valueP(), _("i"), selection_start_i, selection_end_i, selection_start, selection_end, _("Italic")));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ID_FORMAT_UNDERLINE: {
|
case ID_FORMAT_UNDERLINE: {
|
||||||
addAction(toggle_format_action(valueP(), _("u"), selection_start_i, selection_end_i, selection_start, selection_end, _("Underline")));
|
addAction(toggle_format_action(valueP(), _("u"), selection_start_i, selection_end_i, selection_start, selection_end, _("Underline")));
|
||||||
break;
|
break;
|
||||||
|
|||||||
+5
-5
@@ -15,7 +15,7 @@
|
|||||||
#include <data/locale.hpp>
|
#include <data/locale.hpp>
|
||||||
#include <data/installer.hpp>
|
#include <data/installer.hpp>
|
||||||
#include <data/format/formats.hpp>
|
#include <data/format/formats.hpp>
|
||||||
#include <data/font.hpp>
|
#include <data/font.hpp>
|
||||||
#include <cli/cli_main.hpp>
|
#include <cli/cli_main.hpp>
|
||||||
#include <cli/text_io_handler.hpp>
|
#include <cli/text_io_handler.hpp>
|
||||||
#include <gui/welcome_window.hpp>
|
#include <gui/welcome_window.hpp>
|
||||||
@@ -81,13 +81,13 @@ void nag_about_ascii_version() {
|
|||||||
|
|
||||||
int MSE::OnRun() {
|
int MSE::OnRun() {
|
||||||
try {
|
try {
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
SetAppName(_("Magic Set Editor"));
|
SetAppName(_("Magic Set Editor"));
|
||||||
#else
|
#else
|
||||||
// Platform friendly appname
|
// Platform friendly appname
|
||||||
SetAppName(_("magicseteditor"));
|
SetAppName(_("magicseteditor"));
|
||||||
#endif
|
#endif
|
||||||
Font::PreloadResourceFonts(true);
|
Font::PreloadResourceFonts(true);
|
||||||
wxInitAllImageHandlers();
|
wxInitAllImageHandlers();
|
||||||
wxFileSystem::AddHandler(new wxInternetFSHandler); // needed for update checker
|
wxFileSystem::AddHandler(new wxInternetFSHandler); // needed for update checker
|
||||||
wxSocketBase::Initialize();
|
wxSocketBase::Initialize();
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ private:
|
|||||||
if (is_tag(text, tag_start, _( "<b"))) bold += 1;
|
if (is_tag(text, tag_start, _( "<b"))) bold += 1;
|
||||||
else if (is_tag(text, tag_start, _("</b"))) bold -= 1;
|
else if (is_tag(text, tag_start, _("</b"))) bold -= 1;
|
||||||
else if (is_tag(text, tag_start, _( "<i"))) italic += 1;
|
else if (is_tag(text, tag_start, _( "<i"))) italic += 1;
|
||||||
else if (is_tag(text, tag_start, _("</i"))) italic -= 1;
|
else if (is_tag(text, tag_start, _("</i"))) italic -= 1;
|
||||||
else if (is_tag(text, tag_start, _("<u"))) underline += 1;
|
else if (is_tag(text, tag_start, _("<u"))) underline += 1;
|
||||||
else if (is_tag(text, tag_start, _("</u"))) underline -= 1;
|
else if (is_tag(text, tag_start, _("</u"))) underline -= 1;
|
||||||
else if (is_tag(text, tag_start, _( "<sym"))) symbol += 1;
|
else if (is_tag(text, tag_start, _( "<sym"))) symbol += 1;
|
||||||
@@ -301,7 +301,7 @@ private:
|
|||||||
(kwpph > 0 ? FONT_SOFT : FONT_NORMAL) |
|
(kwpph > 0 ? FONT_SOFT : FONT_NORMAL) |
|
||||||
(code > 0 ? FONT_CODE : FONT_NORMAL) |
|
(code > 0 ? FONT_CODE : FONT_NORMAL) |
|
||||||
(code_kw > 0 ? FONT_CODE_KW : FONT_NORMAL) |
|
(code_kw > 0 ? FONT_CODE_KW : FONT_NORMAL) |
|
||||||
(code_string > 0 ? FONT_CODE_STRING : FONT_NORMAL),
|
(code_string > 0 ? FONT_CODE_STRING : FONT_NORMAL),
|
||||||
underline > 0,
|
underline > 0,
|
||||||
fonts.empty() ? nullptr : &fonts.back(),
|
fonts.empty() ? nullptr : &fonts.back(),
|
||||||
param > 0 || param_ref > 0
|
param > 0 || param_ref > 0
|
||||||
|
|||||||
@@ -49,9 +49,10 @@ bool prepare_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& styl
|
|||||||
RealSize size;
|
RealSize size;
|
||||||
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
||||||
// store content properties
|
// store content properties
|
||||||
if (style.content_width != size.width || style.content_height != size.height) {
|
double zoom = dc.getZoom();
|
||||||
style.content_width = size.width / dc.getZoom();
|
if (style.content_width != size.width / zoom || style.content_height != size.height / zoom) {
|
||||||
style.content_height = size.height / dc.getZoom();
|
style.content_width = size.width / zoom;
|
||||||
|
style.content_height = size.height / zoom;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ Bitmap ImageValueViewer::imagePlaceholder(const Rotation& rot, UInt w, UInt h, c
|
|||||||
if (!default_image.Ok()) {
|
if (!default_image.Ok()) {
|
||||||
draw_checker(dc, rect);
|
draw_checker(dc, rect);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (default_image.HasAlpha()) bmp.UseAlpha(true);
|
if (default_image.HasAlpha()) bmp.UseAlpha(true);
|
||||||
dc.DrawImage(default_image, RealPoint(0,0));
|
dc.DrawImage(default_image, RealPoint(0,0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,16 +34,16 @@ void InfoValueViewer::draw(RotatedDC& dc) {
|
|||||||
style().padding_top,
|
style().padding_top,
|
||||||
-style().padding_left - style().padding_right,
|
-style().padding_left - style().padding_right,
|
||||||
-style().padding_top - style().padding_bottom
|
-style().padding_top - style().padding_bottom
|
||||||
);
|
);
|
||||||
// for some reason, while inside the style tab, this value is empty
|
// for some reason, while inside the style tab, this value is empty
|
||||||
// so as a hack for now, if the value is empty, go fetch the caption instead
|
// so as a hack for now, if the value is empty, go fetch the caption instead
|
||||||
if (value().value.empty()) {
|
if (value().value.empty()) {
|
||||||
RealSize size = dc.GetTextExtent(field().caption.get());
|
RealSize size = dc.GetTextExtent(field().caption.get());
|
||||||
dc.DrawText(field().caption.get(), align_in_rect(style().alignment, size, rect));
|
dc.DrawText(field().caption.get(), align_in_rect(style().alignment, size, rect));
|
||||||
}
|
}
|
||||||
// this is what should happen
|
// this is what should happen
|
||||||
else {
|
else {
|
||||||
RealSize size = dc.GetTextExtent(value().value);
|
RealSize size = dc.GetTextExtent(value().value);
|
||||||
dc.DrawText(value().value, align_in_rect(style().alignment, size, rect));
|
dc.DrawText(value().value, align_in_rect(style().alignment, size, rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,14 +279,14 @@ void Context::setVariable(Variable name, const ScriptValueP& value) {
|
|||||||
// keep shadow copy
|
// keep shadow copy
|
||||||
Binding bind = {name, var};
|
Binding bind = {name, var};
|
||||||
shadowed.push_back(bind);
|
shadowed.push_back(bind);
|
||||||
}
|
}
|
||||||
if (!var.global_scope) {
|
if (!var.global_scope) {
|
||||||
var.global_scope = false;
|
var.global_scope = false;
|
||||||
}
|
}
|
||||||
var.level = level;
|
var.level = level;
|
||||||
var.value = value;
|
var.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::setGlobalVariable(Variable name, const ScriptValueP& value) {
|
void Context::setGlobalVariable(Variable name, const ScriptValueP& value) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
assert((size_t)name < variable_names.size());
|
assert((size_t)name < variable_names.size());
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
/// Set a variable to a new value (in the current scope)
|
/// Set a variable to a new value (in the current scope)
|
||||||
void setVariable(const String& name, const ScriptValueP& value);
|
void setVariable(const String& name, const ScriptValueP& value);
|
||||||
/// Set a variable to a new value (in the current scope)
|
/// Set a variable to a new value (in the current scope)
|
||||||
void setVariable(Variable name, const ScriptValueP& value);
|
void setVariable(Variable name, const ScriptValueP& value);
|
||||||
void setGlobalVariable(Variable name, const ScriptValueP& value);
|
void setGlobalVariable(Variable name, const ScriptValueP& value);
|
||||||
|
|
||||||
/// Get the value of a variable, throws if it not set
|
/// Get the value of a variable, throws if it not set
|
||||||
@@ -89,7 +89,7 @@ public:// public for FOR_EACH
|
|||||||
struct VariableValue {
|
struct VariableValue {
|
||||||
VariableValue() : level(0) {}
|
VariableValue() : level(0) {}
|
||||||
unsigned int level; ///< Scope level on which this variable was set
|
unsigned int level; ///< Scope level on which this variable was set
|
||||||
ScriptValueP value; ///< Value of this variable
|
ScriptValueP value; ///< Value of this variable
|
||||||
bool global_scope = false; ///< Is this variable globally scoped?
|
bool global_scope = false; ///< Is this variable globally scoped?
|
||||||
};
|
};
|
||||||
/// Record of a variable binding that is being shadowed (overwritten) by another binding
|
/// Record of a variable binding that is being shadowed (overwritten) by another binding
|
||||||
|
|||||||
@@ -25,21 +25,24 @@
|
|||||||
#include <wx/stdpaths.h>
|
#include <wx/stdpaths.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Debugging
|
// ----------------------------------------------------------------------------- : Debugging
|
||||||
|
|
||||||
SCRIPT_FUNCTION(get_mse_version) {
|
SCRIPT_FUNCTION(get_mse_version) {
|
||||||
SCRIPT_RETURN(app_version.toString());
|
SCRIPT_RETURN(app_version.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(get_mse_path) {
|
SCRIPT_FUNCTION(get_mse_path) {
|
||||||
wxFileName app_path(wxStandardPaths::Get().GetExecutablePath());
|
wxFileName app_path(wxStandardPaths::Get().GetExecutablePath());
|
||||||
String app_folder = app_path.GetPath();
|
String app_folder = app_path.GetPath();
|
||||||
app_folder.Replace("\\", "/");
|
app_folder.Replace("\\", "/");
|
||||||
SCRIPT_RETURN(app_folder);
|
SCRIPT_RETURN(app_folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(get_mse_locale) {
|
||||||
|
SCRIPT_RETURN(settings.locale);
|
||||||
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(trace) {
|
SCRIPT_FUNCTION(trace) {
|
||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
#if defined(_DEBUG) && 0
|
#if defined(_DEBUG) && 0
|
||||||
@@ -82,13 +85,13 @@ SCRIPT_FUNCTION(error) {
|
|||||||
queue_message(MESSAGE_ERROR, input);
|
queue_message(MESSAGE_ERROR, input);
|
||||||
}
|
}
|
||||||
return script_nil;
|
return script_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(exists_in_package) {
|
SCRIPT_FUNCTION(exists_in_package) {
|
||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
bool result = package_manager.existsInPackage(input);
|
bool result = package_manager.existsInPackage(input);
|
||||||
SCRIPT_RETURN(result);
|
SCRIPT_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Conversion
|
// ----------------------------------------------------------------------------- : Conversion
|
||||||
|
|
||||||
@@ -264,11 +267,11 @@ SCRIPT_FUNCTION(to_code) {
|
|||||||
SCRIPT_FUNCTION(to_json) {
|
SCRIPT_FUNCTION(to_json) {
|
||||||
SCRIPT_PARAM_C(ScriptValueP, input);
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
SCRIPT_PARAM_C(Set*, set);
|
SCRIPT_PARAM_C(Set*, set);
|
||||||
SCRIPT_PARAM_DEFAULT(bool, pretty_print, true);
|
SCRIPT_PARAM_DEFAULT(bool, pretty_print, true);
|
||||||
boost::json::value jv = mse_to_json(input, set);
|
boost::json::value jv = mse_to_json(input, set);
|
||||||
|
|
||||||
|
queue_message(MESSAGE_ERROR, json_pretty_print(jv));
|
||||||
|
|
||||||
queue_message(MESSAGE_ERROR, json_pretty_print(jv));
|
|
||||||
|
|
||||||
if (pretty_print) return to_script(json_pretty_print(jv));
|
if (pretty_print) return to_script(json_pretty_print(jv));
|
||||||
else return to_script(json_ugly_print(jv));
|
else return to_script(json_ugly_print(jv));
|
||||||
}
|
}
|
||||||
@@ -704,31 +707,31 @@ SCRIPT_FUNCTION(random_select_many) {
|
|||||||
ret->value.resize(count);
|
ret->value.resize(count);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(make_map) {
|
SCRIPT_FUNCTION(make_map) {
|
||||||
SCRIPT_PARAM(ScriptValueP, keys);
|
SCRIPT_PARAM(ScriptValueP, keys);
|
||||||
SCRIPT_PARAM(ScriptValueP, values);
|
SCRIPT_PARAM(ScriptValueP, values);
|
||||||
ScriptValueP keys_it = keys->makeIterator();
|
ScriptValueP keys_it = keys->makeIterator();
|
||||||
ScriptValueP key;
|
ScriptValueP key;
|
||||||
ScriptValueP values_it = values->makeIterator();
|
ScriptValueP values_it = values->makeIterator();
|
||||||
ScriptValueP value;
|
ScriptValueP value;
|
||||||
ScriptCustomCollectionP map = make_intrusive<ScriptCustomCollection>();
|
ScriptCustomCollectionP map = make_intrusive<ScriptCustomCollection>();
|
||||||
while (key = keys_it->next()) {
|
while (key = keys_it->next()) {
|
||||||
if (key == script_nil) continue;
|
if (key == script_nil) continue;
|
||||||
if (value = values_it->next()) {
|
if (value = values_it->next()) {
|
||||||
map->key_value[key->toString()] = value;
|
map->key_value[key->toString()] = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
queue_message(MESSAGE_WARNING, "More keys than values given in function make_map!");
|
queue_message(MESSAGE_WARNING, "More keys than values given in function make_map!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value = values_it->next()) {
|
if (value = values_it->next()) {
|
||||||
queue_message(MESSAGE_WARNING, "More values than keys given in function make_map!");
|
queue_message(MESSAGE_WARNING, "More values than keys given in function make_map!");
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(get_card_styling) {
|
SCRIPT_FUNCTION(get_card_styling) {
|
||||||
SCRIPT_PARAM_C(ScriptValueP, input);
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
@@ -752,6 +755,45 @@ SCRIPT_FUNCTION(get_card_stylesheet) {
|
|||||||
throw ScriptError(_("invalid set or card argument"));
|
throw ScriptError(_("invalid set or card argument"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(get_card_from_uid) {
|
||||||
|
SCRIPT_PARAM_C(Set*, set);
|
||||||
|
SCRIPT_PARAM_C(String, input);
|
||||||
|
FOR_EACH(other_card, set->cards) {
|
||||||
|
if (other_card->uid == input) SCRIPT_RETURN(other_card);
|
||||||
|
}
|
||||||
|
return script_nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(get_card_from_link) {
|
||||||
|
SCRIPT_PARAM_C(Set*, set);
|
||||||
|
SCRIPT_PARAM_C(CardP, card);
|
||||||
|
SCRIPT_PARAM_C(String, input);
|
||||||
|
String trimmed_input = input.Trim().Trim(false);
|
||||||
|
String uid = card->linked_relation_1 == trimmed_input ? card->linked_card_1 :
|
||||||
|
card->linked_relation_2 == trimmed_input ? card->linked_card_2 :
|
||||||
|
card->linked_relation_3 == trimmed_input ? card->linked_card_3 :
|
||||||
|
card->linked_relation_4 == trimmed_input ? card->linked_card_4 :
|
||||||
|
wxEmptyString;
|
||||||
|
if (uid == wxEmptyString) return script_nil;
|
||||||
|
FOR_EACH(other_card, set->cards) {
|
||||||
|
if (other_card->uid == uid) SCRIPT_RETURN(other_card);
|
||||||
|
}
|
||||||
|
return script_nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(has_link) {
|
||||||
|
SCRIPT_PARAM_C(CardP, card);
|
||||||
|
SCRIPT_PARAM_C(String, input);
|
||||||
|
String trimmed_input = input.Trim().Trim(false);
|
||||||
|
if (
|
||||||
|
card->linked_relation_1 == trimmed_input ||
|
||||||
|
card->linked_relation_2 == trimmed_input ||
|
||||||
|
card->linked_relation_3 == trimmed_input ||
|
||||||
|
card->linked_relation_4 == trimmed_input
|
||||||
|
) SCRIPT_RETURN(true);
|
||||||
|
SCRIPT_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Keywords
|
// ----------------------------------------------------------------------------- : Keywords
|
||||||
|
|
||||||
|
|
||||||
@@ -826,6 +868,7 @@ SCRIPT_FUNCTION(rule) {
|
|||||||
void init_script_basic_functions(Context& ctx) {
|
void init_script_basic_functions(Context& ctx) {
|
||||||
// debugging
|
// debugging
|
||||||
ctx.setVariable(_("get_mse_version"), script_get_mse_version);
|
ctx.setVariable(_("get_mse_version"), script_get_mse_version);
|
||||||
|
ctx.setVariable(_("get_mse_locale"), script_get_mse_locale);
|
||||||
ctx.setVariable(_("get_mse_path"), script_get_mse_path);
|
ctx.setVariable(_("get_mse_path"), script_get_mse_path);
|
||||||
ctx.setVariable(_("trace"), script_trace);
|
ctx.setVariable(_("trace"), script_trace);
|
||||||
ctx.setVariable(_("warning"), script_warning);
|
ctx.setVariable(_("warning"), script_warning);
|
||||||
@@ -842,8 +885,8 @@ void init_script_basic_functions(Context& ctx) {
|
|||||||
ctx.setVariable(_("to_code"), script_to_code);
|
ctx.setVariable(_("to_code"), script_to_code);
|
||||||
ctx.setVariable(_("to_json"), script_to_json);
|
ctx.setVariable(_("to_json"), script_to_json);
|
||||||
ctx.setVariable(_("from_json"), script_from_json);
|
ctx.setVariable(_("from_json"), script_from_json);
|
||||||
ctx.setVariable(_("type_name"), script_type_name);
|
ctx.setVariable(_("type_name"), script_type_name);
|
||||||
ctx.setVariable(_("make_map"), script_make_map);
|
ctx.setVariable(_("make_map"), script_make_map);
|
||||||
ctx.setVariable(_("get_card_styling"), script_get_card_styling);
|
ctx.setVariable(_("get_card_styling"), script_get_card_styling);
|
||||||
ctx.setVariable(_("get_card_stylesheet"), script_get_card_stylesheet);
|
ctx.setVariable(_("get_card_stylesheet"), script_get_card_stylesheet);
|
||||||
// math
|
// math
|
||||||
@@ -891,6 +934,9 @@ void init_script_basic_functions(Context& ctx) {
|
|||||||
ctx.setVariable(_("random_shuffle"), script_random_shuffle);
|
ctx.setVariable(_("random_shuffle"), script_random_shuffle);
|
||||||
ctx.setVariable(_("random_select"), script_random_select);
|
ctx.setVariable(_("random_select"), script_random_select);
|
||||||
ctx.setVariable(_("random_select_many"), script_random_select_many);
|
ctx.setVariable(_("random_select_many"), script_random_select_many);
|
||||||
|
ctx.setVariable(_("get_card_from_uid"), script_get_card_from_uid);
|
||||||
|
ctx.setVariable(_("get_card_from_link"), script_get_card_from_link);
|
||||||
|
ctx.setVariable(_("has_link"), script_has_link);
|
||||||
// keyword
|
// keyword
|
||||||
ctx.setVariable(_("expand_keywords"), script_expand_keywords);
|
ctx.setVariable(_("expand_keywords"), script_expand_keywords);
|
||||||
ctx.setVariable(_("expand_keywords_rule"), make_intrusive<ScriptRule>(script_expand_keywords));
|
ctx.setVariable(_("expand_keywords_rule"), make_intrusive<ScriptRule>(script_expand_keywords));
|
||||||
|
|||||||
@@ -15,131 +15,131 @@
|
|||||||
#include <data/field/choice.hpp>
|
#include <data/field/choice.hpp>
|
||||||
#include <data/field/package_choice.hpp>
|
#include <data/field/package_choice.hpp>
|
||||||
#include <data/field/color.hpp>
|
#include <data/field/color.hpp>
|
||||||
#include <data/field/image.hpp>
|
#include <data/field/image.hpp>
|
||||||
#include <data/game.hpp>
|
#include <data/game.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : new_card
|
// ----------------------------------------------------------------------------- : new_card
|
||||||
|
|
||||||
SCRIPT_FUNCTION(new_card) {
|
SCRIPT_FUNCTION(new_card) {
|
||||||
SCRIPT_PARAM(GameP, game);
|
SCRIPT_PARAM(GameP, game);
|
||||||
SCRIPT_OPTIONAL_PARAM_(bool, ignore_field_not_found);
|
SCRIPT_OPTIONAL_PARAM_(bool, ignore_field_not_found);
|
||||||
// create a new card object
|
// create a new card object
|
||||||
CardP new_card = make_intrusive<Card>(*game);
|
CardP new_card = make_intrusive<Card>(*game);
|
||||||
// iterate on the given key/value pairs
|
// iterate on the given key/value pairs
|
||||||
SCRIPT_PARAM(ScriptValueP, input);
|
SCRIPT_PARAM(ScriptValueP, input);
|
||||||
ScriptValueP it = input->makeIterator();
|
ScriptValueP it = input->makeIterator();
|
||||||
ScriptValueP key;
|
ScriptValueP key;
|
||||||
while (ScriptValueP value = it->next(&key)) {
|
while (ScriptValueP value = it->next(&key)) {
|
||||||
assert(key);
|
assert(key);
|
||||||
if (key == script_nil) continue;
|
if (key == script_nil) continue;
|
||||||
String key_name = key->toString();
|
String key_name = key->toString();
|
||||||
// check if the given value is for a built-in field
|
// check if the given value is for a built-in field
|
||||||
if (set_builtin_container(*game, new_card, value, key_name, ignore_field_not_found)) continue;
|
if (set_builtin_container(*game, new_card, value, key_name, ignore_field_not_found)) continue;
|
||||||
// find the field value (container) that corresponds to the given value
|
// find the field value (container) that corresponds to the given value
|
||||||
Value* container = get_card_field_container(*game, new_card->data, key_name, ignore_field_not_found);
|
Value* container = get_card_field_container(*game, new_card->data, key_name, ignore_field_not_found);
|
||||||
if (container == nullptr) continue;
|
if (container == nullptr) continue;
|
||||||
FieldP field = container->fieldP;
|
FieldP field = container->fieldP;
|
||||||
// if the field has a construction script, set the value and card context variables to be the given value and this card, run script
|
// if the field has a construction script, set the value and card context variables to be the given value and this card, run script
|
||||||
if (field->import_script) {
|
if (field->import_script) {
|
||||||
ScriptValueP ctx_value = ctx.getVariableOpt(SCRIPT_VAR_value);
|
ScriptValueP ctx_value = ctx.getVariableOpt(SCRIPT_VAR_value);
|
||||||
ScriptValueP ctx_card = ctx.getVariableOpt(SCRIPT_VAR_card);
|
ScriptValueP ctx_card = ctx.getVariableOpt(SCRIPT_VAR_card);
|
||||||
ctx.setVariable(SCRIPT_VAR_value, value);
|
ctx.setVariable(SCRIPT_VAR_value, value);
|
||||||
ctx.setVariable(SCRIPT_VAR_card, to_script(new_card));
|
ctx.setVariable(SCRIPT_VAR_card, to_script(new_card));
|
||||||
ScriptValueP script_input = field->import_script.invoke(ctx, true);
|
ScriptValueP script_input = field->import_script.invoke(ctx, true);
|
||||||
// if the script result is a collection, iterate on the key/value pairs
|
// if the script result is a collection, iterate on the key/value pairs
|
||||||
// treat the keys as field names and the values as what to populate those fields with
|
// treat the keys as field names and the values as what to populate those fields with
|
||||||
if (script_input->type() == SCRIPT_COLLECTION) {
|
if (script_input->type() == SCRIPT_COLLECTION) {
|
||||||
ScriptValueP script_it = script_input->makeIterator();
|
ScriptValueP script_it = script_input->makeIterator();
|
||||||
ScriptValueP script_key;
|
ScriptValueP script_key;
|
||||||
while (ScriptValueP script_value = script_it->next(&script_key)) {
|
while (ScriptValueP script_value = script_it->next(&script_key)) {
|
||||||
assert(script_key);
|
assert(script_key);
|
||||||
if (script_key == script_nil) continue;
|
if (script_key == script_nil) continue;
|
||||||
String script_key_name = script_key->toString();
|
String script_key_name = script_key->toString();
|
||||||
// check if the script value is for a built-in field
|
// check if the script value is for a built-in field
|
||||||
if (set_builtin_container(*game, new_card, script_value, script_key_name, ignore_field_not_found)) continue;
|
if (set_builtin_container(*game, new_card, script_value, script_key_name, ignore_field_not_found)) continue;
|
||||||
// find the field value that corresponds to the script value
|
// find the field value that corresponds to the script value
|
||||||
Value* script_container = get_card_field_container(*game, new_card->data, script_key_name, ignore_field_not_found);
|
Value* script_container = get_card_field_container(*game, new_card->data, script_key_name, ignore_field_not_found);
|
||||||
if (script_container == nullptr) continue;
|
if (script_container == nullptr) continue;
|
||||||
// set the field value to the script value
|
// set the field value to the script value
|
||||||
set_container(script_container, script_value, script_key_name);
|
set_container(script_container, script_value, script_key_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if the script result is not a collection, simply set the field value to the script value
|
// if the script result is not a collection, simply set the field value to the script value
|
||||||
else {
|
else {
|
||||||
set_container(container, script_input, key_name);
|
set_container(container, script_input, key_name);
|
||||||
}
|
}
|
||||||
// restore old value and card context variables
|
// restore old value and card context variables
|
||||||
if (ctx_value) ctx.setVariable(SCRIPT_VAR_value, ctx_value);
|
if (ctx_value) ctx.setVariable(SCRIPT_VAR_value, ctx_value);
|
||||||
if (ctx_card) ctx.setVariable(SCRIPT_VAR_card, ctx_card);
|
if (ctx_card) ctx.setVariable(SCRIPT_VAR_card, ctx_card);
|
||||||
}
|
}
|
||||||
// if the field has no construction script, simply set the field value to the given value
|
// if the field has no construction script, simply set the field value to the given value
|
||||||
else {
|
else {
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if the game has a construction script, set the card context variable to be this card, run script
|
// if the game has a construction script, set the card context variable to be this card, run script
|
||||||
if (game->import_script) {
|
if (game->import_script) {
|
||||||
ScriptValueP ctx_card = ctx.getVariableOpt(SCRIPT_VAR_card);
|
ScriptValueP ctx_card = ctx.getVariableOpt(SCRIPT_VAR_card);
|
||||||
ctx.setVariable(SCRIPT_VAR_card, to_script(new_card));
|
ctx.setVariable(SCRIPT_VAR_card, to_script(new_card));
|
||||||
ScriptValueP script_input = game->import_script.invoke(ctx, true);
|
ScriptValueP script_input = game->import_script.invoke(ctx, true);
|
||||||
if (script_input->type() == SCRIPT_COLLECTION) {
|
if (script_input->type() == SCRIPT_COLLECTION) {
|
||||||
// iterate on the key/value pairs given by the script
|
// iterate on the key/value pairs given by the script
|
||||||
ScriptValueP script_it = script_input->makeIterator();
|
ScriptValueP script_it = script_input->makeIterator();
|
||||||
ScriptValueP script_key;
|
ScriptValueP script_key;
|
||||||
while (ScriptValueP script_value = script_it->next(&script_key)) {
|
while (ScriptValueP script_value = script_it->next(&script_key)) {
|
||||||
assert(script_key);
|
assert(script_key);
|
||||||
if (script_key == script_nil) continue;
|
if (script_key == script_nil) continue;
|
||||||
String script_key_name = script_key->toString();
|
String script_key_name = script_key->toString();
|
||||||
// check if the script value is for a built-in field
|
// check if the script value is for a built-in field
|
||||||
if (set_builtin_container(*game, new_card, script_value, script_key_name, ignore_field_not_found)) continue;
|
if (set_builtin_container(*game, new_card, script_value, script_key_name, ignore_field_not_found)) continue;
|
||||||
// find the field value that corresponds to the script value
|
// find the field value that corresponds to the script value
|
||||||
Value* script_container = get_card_field_container(*game, new_card->data, script_key_name, ignore_field_not_found);
|
Value* script_container = get_card_field_container(*game, new_card->data, script_key_name, ignore_field_not_found);
|
||||||
if (script_container == nullptr) continue;
|
if (script_container == nullptr) continue;
|
||||||
// set the field value to the script value
|
// set the field value to the script value
|
||||||
set_container(script_container, script_value, script_key_name);
|
set_container(script_container, script_value, script_key_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
queue_message(MESSAGE_ERROR, _ERROR_("game import script not map"));
|
queue_message(MESSAGE_ERROR, _ERROR_("game import script not map"));
|
||||||
}
|
}
|
||||||
// restore old context card
|
// restore old context card
|
||||||
if (ctx_card) ctx.setVariable(SCRIPT_VAR_card, ctx_card);
|
if (ctx_card) ctx.setVariable(SCRIPT_VAR_card, ctx_card);
|
||||||
}
|
}
|
||||||
SCRIPT_RETURN(new_card);
|
SCRIPT_RETURN(new_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(add_card_to_set) {
|
SCRIPT_FUNCTION(add_card_to_set) {
|
||||||
SCRIPT_PARAM_C(ScriptValueP, input);
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
SCRIPT_PARAM_C(ScriptValueP, set);
|
SCRIPT_PARAM_C(ScriptValueP, set);
|
||||||
ScriptObject<Set*>* s = dynamic_cast<ScriptObject<Set*>*>(set.get());
|
ScriptObject<Set*>* s = dynamic_cast<ScriptObject<Set*>*>(set.get());
|
||||||
if (s) {
|
if (s) {
|
||||||
Set& _set = *s->getValue();
|
Set& _set = *s->getValue();
|
||||||
ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(input.get());
|
ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(input.get());
|
||||||
if (c) {
|
if (c) {
|
||||||
CardP _card = c->getValue();
|
CardP _card = c->getValue();
|
||||||
_set.actions.addAction(make_unique<AddCardAction>(ADD, _set, _card));
|
_set.actions.addAction(make_unique<AddCardAction>(ADD, _set, _card));
|
||||||
SCRIPT_RETURN(true);
|
SCRIPT_RETURN(true);
|
||||||
}
|
}
|
||||||
if (input->type() == SCRIPT_COLLECTION) {
|
if (input->type() == SCRIPT_COLLECTION) {
|
||||||
vector<CardP> _cards;
|
vector<CardP> _cards;
|
||||||
ScriptValueP it = input->makeIterator();
|
ScriptValueP it = input->makeIterator();
|
||||||
ScriptValueP key;
|
ScriptValueP key;
|
||||||
while (ScriptValueP value = it->next(&key)) {
|
while (ScriptValueP value = it->next(&key)) {
|
||||||
c = dynamic_cast<ScriptObject<CardP>*>(value.get());
|
c = dynamic_cast<ScriptObject<CardP>*>(value.get());
|
||||||
if (c) {
|
if (c) {
|
||||||
_cards.push_back(c->getValue());
|
_cards.push_back(c->getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_cards.empty()) {
|
if (!_cards.empty()) {
|
||||||
_set.actions.addAction(make_unique<AddCardAction>(ADD, _set, _cards));
|
_set.actions.addAction(make_unique<AddCardAction>(ADD, _set, _cards));
|
||||||
SCRIPT_RETURN(true);
|
SCRIPT_RETURN(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SCRIPT_RETURN(false);
|
SCRIPT_RETURN(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Init
|
// ----------------------------------------------------------------------------- : Init
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ SCRIPT_FUNCTION(english_number_ordinal) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Singular/plural
|
// ----------------------------------------------------------------------------- : Singular/plural
|
||||||
|
|
||||||
String english_singular(const String& str) {
|
String english_singular(const String& str) {
|
||||||
if (str.Lower() == _("plains")) return str;
|
if (str.Lower() == _("plains")) return str;
|
||||||
if (str.size() > 3 && is_substr(str, str.size()-3, _("ies"))) {
|
if (str.size() > 3 && is_substr(str, str.size()-3, _("ies"))) {
|
||||||
return str.substr(0, str.size() - 3) + _("y");
|
return str.substr(0, str.size() - 3) + _("y");
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ String get_export_full_path(String& rel_name) {
|
|||||||
return fn.GetFullPath();
|
return fn.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure_dir_valid(String& path) {
|
void ensure_dir_valid(String& path) {
|
||||||
if (!wxDirExists(path)) {
|
if (!wxDirExists(path)) {
|
||||||
wxFileName filename = path;
|
wxFileName filename = path;
|
||||||
filename.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
|
filename.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ String to_html(const String& str_in, const SymbolFontP& symbol_font, double symb
|
|||||||
String str = remove_tag_contents(str_in,_("<sep-soft"));
|
String str = remove_tag_contents(str_in,_("<sep-soft"));
|
||||||
String ret;
|
String ret;
|
||||||
Tag bold (_("<b>"), _("</b>")),
|
Tag bold (_("<b>"), _("</b>")),
|
||||||
italic(_("<i>"), _("</i>")),
|
italic(_("<i>"), _("</i>")),
|
||||||
underline(_("<u>"), _("</u>")),
|
underline(_("<u>"), _("</u>")),
|
||||||
symbol(_("<span class=\"symbol\">"), _("</span>"));
|
symbol(_("<span class=\"symbol\">"), _("</span>"));
|
||||||
TagStack tags;
|
TagStack tags;
|
||||||
@@ -232,7 +232,7 @@ String to_html(const String& str_in, const SymbolFontP& symbol_font, double symb
|
|||||||
} else if (is_substr(str, i, _("i"))) {
|
} else if (is_substr(str, i, _("i"))) {
|
||||||
tags.open (ret, italic);
|
tags.open (ret, italic);
|
||||||
} else if (is_substr(str, i, _("/i"))) {
|
} else if (is_substr(str, i, _("/i"))) {
|
||||||
tags.close(ret, italic);
|
tags.close(ret, italic);
|
||||||
} else if (is_substr(str, i, _("u"))) {
|
} else if (is_substr(str, i, _("u"))) {
|
||||||
tags.open(ret, underline);
|
tags.open(ret, underline);
|
||||||
} else if (is_substr(str, i, _("/u"))) {
|
} else if (is_substr(str, i, _("/u"))) {
|
||||||
@@ -312,7 +312,7 @@ String to_bbcode(const String& str_in) {
|
|||||||
String str = remove_tag_contents(str_in,_("<sep-soft"));
|
String str = remove_tag_contents(str_in,_("<sep-soft"));
|
||||||
String ret;
|
String ret;
|
||||||
Tag bold (_("[b]"), _("[/b]")),
|
Tag bold (_("[b]"), _("[/b]")),
|
||||||
italic(_("[i]"), _("[/i]")),
|
italic(_("[i]"), _("[/i]")),
|
||||||
underline(_("[u]"), _("[/u]"));
|
underline(_("[u]"), _("[/u]"));
|
||||||
TagStack tags;
|
TagStack tags;
|
||||||
String symbols;
|
String symbols;
|
||||||
@@ -332,7 +332,7 @@ String to_bbcode(const String& str_in) {
|
|||||||
tags.open(ret, underline);
|
tags.open(ret, underline);
|
||||||
} else if (is_substr(str, i, _("/u"))) {
|
} else if (is_substr(str, i, _("/u"))) {
|
||||||
tags.close(ret, underline);
|
tags.close(ret, underline);
|
||||||
}
|
}
|
||||||
/*else if (is_substr(str, i, _("sym"))) {
|
/*else if (is_substr(str, i, _("sym"))) {
|
||||||
tags.open (ret, symbol);
|
tags.open (ret, symbol);
|
||||||
} else if (is_substr(str, i, _("/sym"))) {
|
} else if (is_substr(str, i, _("/sym"))) {
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/symbol.hpp>
|
#include <data/symbol.hpp>
|
||||||
#include <data/field/symbol.hpp>
|
#include <data/field/symbol.hpp>
|
||||||
#include <data/format/formats.hpp>
|
#include <data/format/formats.hpp>
|
||||||
#include <gfx/generated_image.hpp>
|
#include <gfx/generated_image.hpp>
|
||||||
#include <render/symbol/filter.hpp>
|
#include <render/symbol/filter.hpp>
|
||||||
#include <cli/text_io_handler.hpp> // for MSE_CLI
|
#include <cli/text_io_handler.hpp> // for MSE_CLI
|
||||||
|
|
||||||
void parse_enum(const String&, ImageCombine& out);
|
void parse_enum(const String&, ImageCombine& out);
|
||||||
|
|
||||||
@@ -29,45 +29,55 @@ SCRIPT_FUNCTION(to_image) {
|
|||||||
SCRIPT_PARAM_C(GeneratedImageP, input);
|
SCRIPT_PARAM_C(GeneratedImageP, input);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(to_card_image) {
|
SCRIPT_FUNCTION(to_card_image) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(CardP, input);
|
SCRIPT_PARAM(CardP, input);
|
||||||
SCRIPT_PARAM_DEFAULT(double, zoom, 100);
|
SCRIPT_PARAM_DEFAULT(double, zoom, 100);
|
||||||
SCRIPT_PARAM_DEFAULT(Degrees, angle, 0);
|
SCRIPT_PARAM_DEFAULT(Degrees, angle, 0);
|
||||||
SCRIPT_PARAM_DEFAULT(bool, use_user_settings, false);
|
SCRIPT_PARAM_DEFAULT(bool, use_user_settings, false);
|
||||||
if (use_user_settings) {
|
if (use_user_settings) {
|
||||||
// Use the User's Preferences for Export Zoom and Angle settings.
|
// Use the User's Preferences for Export Zoom and Angle settings.
|
||||||
return make_intrusive<ArbitraryImage>(export_bitmap(set, input).ConvertToImage());
|
return make_intrusive<ArbitraryImage>(export_bitmap(set, input).ConvertToImage());
|
||||||
} else {
|
} else {
|
||||||
// Use the provided (or defaulted) Zoom and Angle.
|
// Use the provided (or defaulted) Zoom and Angle.
|
||||||
return make_intrusive<ArbitraryImage>(export_bitmap(set, input, (zoom / 100), deg_to_rad(angle)).ConvertToImage());
|
return make_intrusive<ArbitraryImage>(export_bitmap(set, input, (zoom / 100), deg_to_rad(angle)).ConvertToImage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(import_image) {
|
SCRIPT_FUNCTION(import_image) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(String, input);
|
SCRIPT_PARAM(String, input);
|
||||||
auto extImg = make_intrusive<ExternalImage>(input);
|
auto extImg = make_intrusive<ExternalImage>(input);
|
||||||
if (cli.haveConsole()) // makes sure generate() is called, but only once, when using the CLI
|
if (cli.haveConsole()) // makes sure generate() is called, but only once, when using the CLI
|
||||||
extImg->generate(GeneratedImage::Options(0, 0, set->stylesheet.get(), set));
|
extImg->generate(GeneratedImage::Options(0, 0, set->stylesheet.get(), set));
|
||||||
return extImg;
|
return extImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Image functions
|
// ----------------------------------------------------------------------------- : Image functions
|
||||||
|
|
||||||
SCRIPT_FUNCTION(width_of) {
|
SCRIPT_FUNCTION(width_of) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(GeneratedImageP, input);
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
Image image = input->generate(GeneratedImage::Options(0, 0, set->stylesheet.get()));
|
Image image = input->generate(GeneratedImage::Options(0, 0, set->stylesheet.get()));
|
||||||
SCRIPT_RETURN(image.GetWidth());
|
SCRIPT_RETURN(image.GetWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(height_of) {
|
SCRIPT_FUNCTION(height_of) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(GeneratedImageP, input);
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
Image image = input->generate(GeneratedImage::Options(0, 0, set->stylesheet.get()));
|
Image image = input->generate(GeneratedImage::Options(0, 0, set->stylesheet.get()));
|
||||||
SCRIPT_RETURN(image.GetHeight());
|
SCRIPT_RETURN(image.GetHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(dimensions_of) {
|
||||||
|
SCRIPT_PARAM(Set*, set);
|
||||||
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
|
Image image = input->generate(GeneratedImage::Options(0, 0, set->stylesheet.get()));
|
||||||
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
|
ret->value.push_back(to_script(image.GetWidth()));
|
||||||
|
ret->value.push_back(to_script(image.GetHeight()));
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(insert_image) {
|
SCRIPT_FUNCTION(insert_image) {
|
||||||
@@ -77,7 +87,7 @@ SCRIPT_FUNCTION(insert_image) {
|
|||||||
SCRIPT_PARAM(int, offset_y);
|
SCRIPT_PARAM(int, offset_y);
|
||||||
SCRIPT_OPTIONAL_PARAM_(Color, background_color);
|
SCRIPT_OPTIONAL_PARAM_(Color, background_color);
|
||||||
return make_intrusive<InsertedImage>(base_image, inserted_image, offset_x, offset_y, background_color);
|
return make_intrusive<InsertedImage>(base_image, inserted_image, offset_x, offset_y, background_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(linear_blend) {
|
SCRIPT_FUNCTION(linear_blend) {
|
||||||
SCRIPT_PARAM(GeneratedImageP, image1);
|
SCRIPT_PARAM(GeneratedImageP, image1);
|
||||||
@@ -273,10 +283,11 @@ SCRIPT_FUNCTION(built_in_image) {
|
|||||||
// ----------------------------------------------------------------------------- : Init
|
// ----------------------------------------------------------------------------- : Init
|
||||||
|
|
||||||
void init_script_image_functions(Context& ctx) {
|
void init_script_image_functions(Context& ctx) {
|
||||||
ctx.setVariable(_("to_image"), script_to_image);
|
ctx.setVariable(_("to_image"), script_to_image);
|
||||||
ctx.setVariable(_("to_card_image"), script_to_card_image);
|
ctx.setVariable(_("to_card_image"), script_to_card_image);
|
||||||
ctx.setVariable(_("width_of"), script_width_of);
|
ctx.setVariable(_("width_of"), script_width_of);
|
||||||
ctx.setVariable(_("height_of"), script_height_of);
|
ctx.setVariable(_("height_of"), script_height_of);
|
||||||
|
ctx.setVariable(_("dimensions_of"), script_dimensions_of);
|
||||||
ctx.setVariable(_("linear_blend"), script_linear_blend);
|
ctx.setVariable(_("linear_blend"), script_linear_blend);
|
||||||
ctx.setVariable(_("masked_blend"), script_masked_blend);
|
ctx.setVariable(_("masked_blend"), script_masked_blend);
|
||||||
ctx.setVariable(_("combine_blend"), script_combine_blend);
|
ctx.setVariable(_("combine_blend"), script_combine_blend);
|
||||||
@@ -298,5 +309,5 @@ void init_script_image_functions(Context& ctx) {
|
|||||||
ctx.setVariable(_("drop_shadow"), script_drop_shadow);
|
ctx.setVariable(_("drop_shadow"), script_drop_shadow);
|
||||||
ctx.setVariable(_("symbol_variation"), script_symbol_variation);
|
ctx.setVariable(_("symbol_variation"), script_symbol_variation);
|
||||||
ctx.setVariable(_("built_in_image"), script_built_in_image);
|
ctx.setVariable(_("built_in_image"), script_built_in_image);
|
||||||
ctx.setVariable(_("import_image"), script_import_image);
|
ctx.setVariable(_("import_image"), script_import_image);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ void TokenIterator::readToken() {
|
|||||||
newline = true;
|
newline = true;
|
||||||
} else if (isSpace(c)) {
|
} else if (isSpace(c)) {
|
||||||
++pos;
|
++pos;
|
||||||
// ignore
|
// ignore
|
||||||
} else if (is_substr(pos, end, "include localized file:")) {
|
} else if (is_substr(pos, end, "include localized file:")) {
|
||||||
pos += 23; // "include localized file:"
|
pos += 23; // "include localized file:"
|
||||||
const char* newlines = "\r\n";
|
const char* newlines = "\r\n";
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ void init_script_variables() {
|
|||||||
Var(stylesheet);
|
Var(stylesheet);
|
||||||
Var(card_style);
|
Var(card_style);
|
||||||
Var(card);
|
Var(card);
|
||||||
Var(styling);
|
Var(styling);
|
||||||
Var(extra_card_style);
|
Var(extra_card_style);
|
||||||
Var(extra_card);
|
Var(extra_card);
|
||||||
Var(value);
|
Var(value);
|
||||||
Var(condition);
|
Var(condition);
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ enum Variable
|
|||||||
, SCRIPT_VAR_stylesheet
|
, SCRIPT_VAR_stylesheet
|
||||||
, SCRIPT_VAR_card_style
|
, SCRIPT_VAR_card_style
|
||||||
, SCRIPT_VAR_card
|
, SCRIPT_VAR_card
|
||||||
, SCRIPT_VAR_styling
|
, SCRIPT_VAR_styling
|
||||||
, SCRIPT_VAR_extra_card_style
|
, SCRIPT_VAR_extra_card_style
|
||||||
, SCRIPT_VAR_extra_card
|
, SCRIPT_VAR_extra_card
|
||||||
, SCRIPT_VAR_value
|
, SCRIPT_VAR_value
|
||||||
, SCRIPT_VAR_condition
|
, SCRIPT_VAR_condition
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ Context& SetScriptContext::getContext(const StyleSheetP& stylesheet) {
|
|||||||
ctx.setVariable(SCRIPT_VAR_set, make_intrusive<ScriptObject<Set*>>(&set));
|
ctx.setVariable(SCRIPT_VAR_set, make_intrusive<ScriptObject<Set*>>(&set));
|
||||||
ctx.setVariable(SCRIPT_VAR_game, to_script(set.game));
|
ctx.setVariable(SCRIPT_VAR_game, to_script(set.game));
|
||||||
ctx.setVariable(SCRIPT_VAR_stylesheet, to_script(stylesheet));
|
ctx.setVariable(SCRIPT_VAR_stylesheet, to_script(stylesheet));
|
||||||
ctx.setVariable(SCRIPT_VAR_card_style, to_script(&stylesheet->card_style));
|
ctx.setVariable(SCRIPT_VAR_card_style, to_script(&stylesheet->card_style));
|
||||||
|
|
||||||
// I'm not entirely clear on why a "dummy value" is necessary here.
|
// I'm not entirely clear on why a "dummy value" is necessary here.
|
||||||
// It doesn't appear that these are getting accessed until a card is found anyways, so they don't trip any errors that I could see.
|
// It doesn't appear that these are getting accessed until a card is found anyways, so they don't trip any errors that I could see.
|
||||||
// Retaining the format just for consistency in case there's something that I missed.
|
// Retaining the format just for consistency in case there's something that I missed.
|
||||||
ctx.setVariable(SCRIPT_VAR_card, set.cards.empty() ? script_nil : to_script(set.cards.front())); // dummy value
|
ctx.setVariable(SCRIPT_VAR_card, set.cards.empty() ? script_nil : to_script(set.cards.front())); // dummy value
|
||||||
ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(*stylesheet)));
|
ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(*stylesheet)));
|
||||||
ctx.setVariable(SCRIPT_VAR_extra_card_style, to_script(&stylesheet->extra_card_style)); // dummy value
|
ctx.setVariable(SCRIPT_VAR_extra_card_style, to_script(&stylesheet->extra_card_style)); // dummy value
|
||||||
ctx.setVariable(SCRIPT_VAR_extra_card, set.cards.empty() ? script_nil : to_script(&set.cards.front()->extraDataFor(*stylesheet))); // dummy value
|
ctx.setVariable(SCRIPT_VAR_extra_card, set.cards.empty() ? script_nil : to_script(&set.cards.front()->extraDataFor(*stylesheet))); // dummy value
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -73,13 +73,13 @@ Context& SetScriptContext::getContext(const CardP& card) {
|
|||||||
Context& ctx = getContext(stylesheet);
|
Context& ctx = getContext(stylesheet);
|
||||||
if (card) {
|
if (card) {
|
||||||
ctx.setVariable(SCRIPT_VAR_card, to_script(card));
|
ctx.setVariable(SCRIPT_VAR_card, to_script(card));
|
||||||
ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(card)));
|
ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(card)));
|
||||||
ctx.setVariable(SCRIPT_VAR_extra_card_style, to_script(&stylesheet->extra_card_style));
|
ctx.setVariable(SCRIPT_VAR_extra_card_style, to_script(&stylesheet->extra_card_style));
|
||||||
ctx.setVariable(SCRIPT_VAR_extra_card, to_script(&card->extraDataFor(*stylesheet)));
|
ctx.setVariable(SCRIPT_VAR_extra_card, to_script(&card->extraDataFor(*stylesheet)));
|
||||||
} else {
|
} else {
|
||||||
ctx.setVariable(SCRIPT_VAR_card, ScriptValueP());
|
ctx.setVariable(SCRIPT_VAR_card, ScriptValueP());
|
||||||
ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(*stylesheet)));
|
ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(*stylesheet)));
|
||||||
ctx.setVariable(SCRIPT_VAR_extra_card_style, script_nil);
|
ctx.setVariable(SCRIPT_VAR_extra_card_style, script_nil);
|
||||||
ctx.setVariable(SCRIPT_VAR_extra_card, script_nil);
|
ctx.setVariable(SCRIPT_VAR_extra_card, script_nil);
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ bool Package::existsIn(const String& file) {
|
|||||||
if (filename.find(_(".mse-")) != String::npos) {
|
if (filename.find(_(".mse-")) != String::npos) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<wxInputStream> stream;
|
unique_ptr<wxInputStream> stream;
|
||||||
if (it != files.end() && it->second.wasWritten()) {
|
if (it != files.end() && it->second.wasWritten()) {
|
||||||
@@ -216,7 +216,7 @@ bool Package::existsIn(const String& file) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return stream && stream->IsOk();
|
return stream && stream->IsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<wxInputStream> Package::openIn(const String& file) {
|
unique_ptr<wxInputStream> Package::openIn(const String& file) {
|
||||||
if (!file.empty() && file.GetChar(0) == _('/')) {
|
if (!file.empty() && file.GetChar(0) == _('/')) {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ bool PackageManager::existsInPackage(const String& name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw FileNotFoundError(name, _("No package name specified, use '/package/filename'"));
|
throw FileNotFoundError(name, _("No package name specified, use '/package/filename'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<unique_ptr<wxInputStream>,Packaged*> PackageManager::openFileFromPackage(Packaged* package, const String& name) {
|
pair<unique_ptr<wxInputStream>,Packaged*> PackageManager::openFileFromPackage(Packaged* package, const String& name) {
|
||||||
if (!name.empty() && name.GetChar(0) == _('/')) {
|
if (!name.empty() && name.GetChar(0) == _('/')) {
|
||||||
|
|||||||
@@ -357,10 +357,10 @@ template <> void Reader::handle(Vector2D& vec) {
|
|||||||
template <> void Reader::handle(LocalFileName& f) {
|
template <> void Reader::handle(LocalFileName& f) {
|
||||||
f = LocalFileName::fromReadString(this->getValue());
|
f = LocalFileName::fromReadString(this->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
String Reader::addLocale(String filename) {
|
String Reader::addLocale(String filename) {
|
||||||
return filename + _("_") + settings.locale;
|
return filename + _("_") + settings.locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : EnumReader
|
// ----------------------------------------------------------------------------- : EnumReader
|
||||||
|
|
||||||
|
|||||||
@@ -116,9 +116,9 @@ public:
|
|||||||
|
|
||||||
/// The package being read from
|
/// The package being read from
|
||||||
inline Packaged* getPackage() const { return package; }
|
inline Packaged* getPackage() const { return package; }
|
||||||
|
|
||||||
String addLocale(String);
|
String addLocale(String);
|
||||||
|
|
||||||
/// Set the value that will be returned by the next getValue() call (may mess up the state of the reader)
|
/// Set the value that will be returned by the next getValue() call (may mess up the state of the reader)
|
||||||
inline void setValue(const String& value) { state = UNHANDLED; previous_value = value; };
|
inline void setValue(const String& value) { state = UNHANDLED; previous_value = value; };
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ private:
|
|||||||
/** Maybe the key is "include file" */
|
/** Maybe the key is "include file" */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void unknownKey(T& v) {
|
void unknownKey(T& v) {
|
||||||
if (key == _("include_file") || key == _("include_localized_file")) {
|
if (key == _("include_file") || key == _("include_localized_file")) {
|
||||||
value = key == _("include_localized_file") ? addLocale(value) : value;
|
value = key == _("include_localized_file") ? addLocale(value) : value;
|
||||||
auto [stream, include_package] = openFileFromPackage(package, value);
|
auto [stream, include_package] = openFileFromPackage(package, value);
|
||||||
Reader sub_reader(*stream, include_package, value, ignore_invalid);
|
Reader sub_reader(*stream, include_package, value, ignore_invalid);
|
||||||
|
|||||||
+6
-6
@@ -50,14 +50,14 @@ String tr(LocaleCategory cat, const String& key, DefaultLocaleFun def = warn_and
|
|||||||
|
|
||||||
/// Translate 'key' in the for a Package using the current locale
|
/// Translate 'key' in the for a Package using the current locale
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
String tr(const Package&, const String& key, DefaultLocaleFun def);
|
String tr(const Package&, const String& key, DefaultLocaleFun def);
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
String tr(const String&, const String& key, DefaultLocaleFun def);
|
String tr(const String&, const String& key, DefaultLocaleFun def);
|
||||||
|
|
||||||
/// Translate 'key' in the for a Package using the current locale
|
/// Translate 'key' in the for a Package using the current locale
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
String tr(const Package&, const String& subcat, const String& key, DefaultLocaleFun def);
|
String tr(const Package&, const String& subcat, const String& key, DefaultLocaleFun def);
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
String tr(const String&, const String& subcat, const String& key, DefaultLocaleFun def);
|
String tr(const String&, const String& subcat, const String& key, DefaultLocaleFun def);
|
||||||
|
|
||||||
/// A localized string for menus
|
/// A localized string for menus
|
||||||
@@ -99,9 +99,9 @@ String tr(const String&, const String& subcat, const String& key, DefaultLocaleF
|
|||||||
#define _TOOLTIP_1_(s,a) format_string(_TOOLTIP_(s), a)
|
#define _TOOLTIP_1_(s,a) format_string(_TOOLTIP_(s), a)
|
||||||
|
|
||||||
/// A localized string for tooltip labels, with 1 argument (printf style)
|
/// A localized string for tooltip labels, with 1 argument (printf style)
|
||||||
#define _LABEL_1_(s,a) format_string(_LABEL_(s), a)
|
#define _LABEL_1_(s,a) format_string(_LABEL_(s), a)
|
||||||
/// A localized string for tooltip labels, with 2 argument (printf style)
|
/// A localized string for tooltip labels, with 2 argument (printf style)
|
||||||
#define _LABEL_2_(s,a,b) format_string(_LABEL_(s), a, b)
|
#define _LABEL_2_(s,a,b) format_string(_LABEL_(s), a, b)
|
||||||
/// A localized string for tooltip labels, with 3 argument (printf style)
|
/// A localized string for tooltip labels, with 3 argument (printf style)
|
||||||
#define _LABEL_3_(s,a,b,c) format_string(_LABEL_(s), a, b, c)
|
#define _LABEL_3_(s,a,b,c) format_string(_LABEL_(s), a, b, c)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -137,14 +137,14 @@ void uncanonical_name_form_in_place(String& str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String unified_form(String& str) {
|
String unified_form(String& str) {
|
||||||
str = trim(str);
|
str = trim(str);
|
||||||
for (String::iterator it = str.begin(); it != str.end(); ++it) {
|
for (String::iterator it = str.begin(); it != str.end(); ++it) {
|
||||||
if (*it == ' ') *it = '_';
|
if (*it == ' ') *it = '_';
|
||||||
else *it = toLower(*it);
|
else *it = toLower(*it);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name_to_caption(const String& str) {
|
String name_to_caption(const String& str) {
|
||||||
String ret;
|
String ret;
|
||||||
|
|||||||
+3
-3
@@ -241,9 +241,9 @@ void uncanonical_name_form_in_place(String&);
|
|||||||
inline String uncanonical_name_form(String s) {
|
inline String uncanonical_name_form(String s) {
|
||||||
uncanonical_name_form_in_place(s);
|
uncanonical_name_form_in_place(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a field name to canonical form, then to lower case, then trim it
|
/// Convert a field name to canonical form, then to lower case, then trim it
|
||||||
String unified_form(String&);
|
String unified_form(String&);
|
||||||
|
|
||||||
/// Convert a field name to a string that can be shown to the user
|
/// Convert a field name to a string that can be shown to the user
|
||||||
|
|||||||
@@ -645,9 +645,9 @@ String simplify_tagged(const String& str) {
|
|||||||
// (where </tag> is the negation of tag)
|
// (where </tag> is the negation of tag)
|
||||||
bool add_or_cancel_tag(const String& tag, String& stack, bool all = false) {
|
bool add_or_cancel_tag(const String& tag, String& stack, bool all = false) {
|
||||||
if (all || starts_with(tag, _("/")) ||
|
if (all || starts_with(tag, _("/")) ||
|
||||||
starts_with(tag, _("b")) ||
|
starts_with(tag, _("b")) ||
|
||||||
starts_with(tag, _("i")) ||
|
starts_with(tag, _("i")) ||
|
||||||
starts_with(tag, _("u")) ||
|
starts_with(tag, _("u")) ||
|
||||||
starts_with(tag, _("sym"))) {
|
starts_with(tag, _("sym"))) {
|
||||||
// cancel out all close tags, but not all open tags,
|
// cancel out all close tags, but not all open tags,
|
||||||
// so <xx></xx> is always removed
|
// so <xx></xx> is always removed
|
||||||
@@ -695,9 +695,9 @@ String simplify_tagged_overlap(const String& str) {
|
|||||||
Char c = str.GetChar(i);
|
Char c = str.GetChar(i);
|
||||||
if (c == _('<')) {
|
if (c == _('<')) {
|
||||||
String tag = tag_at(str, i);
|
String tag = tag_at(str, i);
|
||||||
if (starts_with(tag, _("b")) || starts_with(tag, _("/b")) ||
|
if (starts_with(tag, _("b")) || starts_with(tag, _("/b")) ||
|
||||||
starts_with(tag, _("i")) || starts_with(tag, _("/i")) ||
|
starts_with(tag, _("i")) || starts_with(tag, _("/i")) ||
|
||||||
starts_with(tag, _("u")) || starts_with(tag, _("/u")) ||
|
starts_with(tag, _("u")) || starts_with(tag, _("/u")) ||
|
||||||
starts_with(tag, _("sym")) || starts_with(tag, _("/sym"))) {
|
starts_with(tag, _("sym")) || starts_with(tag, _("/sym"))) {
|
||||||
// optimize this tag
|
// optimize this tag
|
||||||
if (open_tags.find(_("<") + tag + _(">")) == String::npos) {
|
if (open_tags.find(_("<") + tag + _(">")) == String::npos) {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : UID
|
||||||
|
|
||||||
|
static std::random_device rd; // Get true random number generator
|
||||||
|
static std::mt19937_64 gen((static_cast<uint64_t>(rd()) << 32) ^ rd()); // Bitwise XOR two outputs to seed pseudo random number generator
|
||||||
|
static std::uniform_int_distribution<> dis(0, 9);
|
||||||
|
|
||||||
|
// Generate a string consisting of 32 uniformly random digits.
|
||||||
|
static String generate_uid() {
|
||||||
|
std::stringstream ss;
|
||||||
|
int i;
|
||||||
|
ss << std::hex;
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
ss << dis(gen);
|
||||||
|
};
|
||||||
|
//return ss.str();
|
||||||
|
String wxString(ss.str().c_str(), wxConvUTF8);
|
||||||
|
return wxString;
|
||||||
|
}
|
||||||
@@ -51,14 +51,14 @@ template <> void GetDefaultMember::handle(const Version& v) {
|
|||||||
// ----------------------------------------------------------------------------- : Versions
|
// ----------------------------------------------------------------------------- : Versions
|
||||||
|
|
||||||
// NOTE: Don't use leading zeroes, they mean octal
|
// NOTE: Don't use leading zeroes, they mean octal
|
||||||
const Version app_version = 10000 * MSE_VERSION_MAJOR + 100 * MSE_VERSION_MINOR + MSE_VERSION_PATCH;
|
const Version app_version = 10000 * MSE_VERSION_MAJOR + 100 * MSE_VERSION_MINOR + MSE_VERSION_PATCH;
|
||||||
|
|
||||||
#if defined UNOFFICIAL_BUILD
|
#if defined UNOFFICIAL_BUILD
|
||||||
const Char* version_suffix = _(" (Unofficial)");
|
const Char* version_suffix = _(" (Unofficial)");
|
||||||
#elif defined UNICODE
|
#elif defined UNICODE
|
||||||
const Char* version_suffix = _("");
|
const Char* version_suffix = _("");
|
||||||
#else
|
#else
|
||||||
const Char* version_suffix = _(" (ascii build)");
|
const Char* version_suffix = _(" (ascii build)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Which version of MSE are the files we write out compatible with?
|
/// Which version of MSE are the files we write out compatible with?
|
||||||
|
|||||||
+24
-9
@@ -81,7 +81,7 @@ enum MenuID {
|
|||||||
ID_MODE_SYMMETRY,
|
ID_MODE_SYMMETRY,
|
||||||
ID_MODE_PAINT,
|
ID_MODE_PAINT,
|
||||||
ID_MODE_MAX,
|
ID_MODE_MAX,
|
||||||
|
|
||||||
// Welcome Window
|
// Welcome Window
|
||||||
ID_SELECT_LANGUAGE,
|
ID_SELECT_LANGUAGE,
|
||||||
};
|
};
|
||||||
@@ -108,12 +108,14 @@ enum ChildMenuID {
|
|||||||
ID_CARD_ROTATE_270,
|
ID_CARD_ROTATE_270,
|
||||||
// CardList
|
// CardList
|
||||||
ID_SELECT_COLUMNS,
|
ID_SELECT_COLUMNS,
|
||||||
|
ID_CARD_LINK,
|
||||||
|
ID_CARD_AND_LINK_COPY,
|
||||||
ID_CARD_ADD_CSV,
|
ID_CARD_ADD_CSV,
|
||||||
ID_CARD_ADD_CSV_SEP,
|
ID_CARD_ADD_CSV_SEP,
|
||||||
ID_CARD_ADD_CSV_BROWSE,
|
ID_CARD_ADD_CSV_BROWSE,
|
||||||
ID_CARD_ADD_JSON,
|
ID_CARD_ADD_JSON,
|
||||||
ID_CARD_ADD_JSON_ARRAY,
|
ID_CARD_ADD_JSON_ARRAY,
|
||||||
ID_CARD_ADD_JSON_BROWSE,
|
ID_CARD_ADD_JSON_BROWSE,
|
||||||
|
|
||||||
// Keyword menu
|
// Keyword menu
|
||||||
ID_KEYWORD_ADD = 6101,
|
ID_KEYWORD_ADD = 6101,
|
||||||
@@ -124,7 +126,7 @@ enum ChildMenuID {
|
|||||||
|
|
||||||
// Format menu
|
// Format menu
|
||||||
ID_FORMAT_BOLD = 6201,
|
ID_FORMAT_BOLD = 6201,
|
||||||
ID_FORMAT_ITALIC,
|
ID_FORMAT_ITALIC,
|
||||||
ID_FORMAT_UNDERLINE,
|
ID_FORMAT_UNDERLINE,
|
||||||
ID_FORMAT_SYMBOL,
|
ID_FORMAT_SYMBOL,
|
||||||
ID_FORMAT_REMINDER,
|
ID_FORMAT_REMINDER,
|
||||||
@@ -192,6 +194,12 @@ enum ChildMenuID {
|
|||||||
ID_COLLAPSE_NOTES = 8001,
|
ID_COLLAPSE_NOTES = 8001,
|
||||||
ID_CARD_FILTER,
|
ID_CARD_FILTER,
|
||||||
ID_CARD_COUNTER,
|
ID_CARD_COUNTER,
|
||||||
|
ID_CARD_LINK_TYPE,
|
||||||
|
ID_CARD_LINK_SELECT,
|
||||||
|
ID_CARD_LINK_UNLINK_1,
|
||||||
|
ID_CARD_LINK_UNLINK_2,
|
||||||
|
ID_CARD_LINK_UNLINK_3,
|
||||||
|
ID_CARD_LINK_UNLINK_4,
|
||||||
|
|
||||||
// Style panel
|
// Style panel
|
||||||
ID_STYLE_USE_FOR_ALL = 8011,
|
ID_STYLE_USE_FOR_ALL = 8011,
|
||||||
@@ -219,7 +227,7 @@ enum ChildMenuID {
|
|||||||
ID_CUSTOM_PACK,
|
ID_CUSTOM_PACK,
|
||||||
|
|
||||||
// Console panel
|
// Console panel
|
||||||
ID_EVALUATE,
|
ID_EVALUATE,
|
||||||
ID_CLEAR_CONSOLE,
|
ID_CLEAR_CONSOLE,
|
||||||
|
|
||||||
// SymbolFont (Format menu)
|
// SymbolFont (Format menu)
|
||||||
@@ -279,12 +287,13 @@ enum ControlID {
|
|||||||
ID_PREVIEW,
|
ID_PREVIEW,
|
||||||
ID_SELECTOR,
|
ID_SELECTOR,
|
||||||
ID_SIZE,
|
ID_SIZE,
|
||||||
|
ID_GRID,
|
||||||
ID_LEFT,
|
ID_LEFT,
|
||||||
ID_TOP,
|
ID_TOP,
|
||||||
ID_WIDTH,
|
ID_WIDTH,
|
||||||
ID_HEIGHT,
|
ID_HEIGHT,
|
||||||
ID_SELECTION_CENTER,
|
ID_SELECTION_CENTER,
|
||||||
ID_SELECTION_CENTER_HORIZONTALLY,
|
ID_SELECTION_CENTER_HORIZONTALLY,
|
||||||
ID_SELECTION_CENTER_VERTICALLY,
|
ID_SELECTION_CENTER_VERTICALLY,
|
||||||
ID_FIX_ASPECT,
|
ID_FIX_ASPECT,
|
||||||
ID_ZOOM,
|
ID_ZOOM,
|
||||||
@@ -294,8 +303,8 @@ enum ControlID {
|
|||||||
ID_EXPORT_ZOOM_X,
|
ID_EXPORT_ZOOM_X,
|
||||||
ID_EXPORT_ZOOM_Y,
|
ID_EXPORT_ZOOM_Y,
|
||||||
ID_SHARPEN,
|
ID_SHARPEN,
|
||||||
ID_SHARPEN_AMOUNT,
|
ID_SHARPEN_AMOUNT,
|
||||||
// Internal window
|
// Internal window
|
||||||
ID_INTERNAL_SCALE,
|
ID_INTERNAL_SCALE,
|
||||||
// Updates window
|
// Updates window
|
||||||
ID_PACKAGE_LIST,
|
ID_PACKAGE_LIST,
|
||||||
@@ -309,5 +318,11 @@ enum ControlID {
|
|||||||
ID_ADD_ITEM,
|
ID_ADD_ITEM,
|
||||||
ID_REMOVE_ITEM,
|
ID_REMOVE_ITEM,
|
||||||
ID_DEFAULTS,
|
ID_DEFAULTS,
|
||||||
|
ID_CARD_LINK_EDITOR,
|
||||||
|
ID_CARD_LINK_VIEWER,
|
||||||
|
ID_CARD_LINK_RELATION_1,
|
||||||
|
ID_CARD_LINK_RELATION_2,
|
||||||
|
ID_CARD_LINK_RELATION_3,
|
||||||
|
ID_CARD_LINK_RELATION_4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once('./modules/mse-drupal-modules/autoformat.inc');
|
require_once('./modules/mse-drupal-modules/autoformat.inc');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,28 +18,28 @@ function autoformat_help($section) {
|
|||||||
*/
|
*/
|
||||||
function autoformat_filter_tips($delta, $format, $long = FALSE) {
|
function autoformat_filter_tips($delta, $format, $long = FALSE) {
|
||||||
if ($long) {
|
if ($long) {
|
||||||
$tips = array(
|
$tips = array(
|
||||||
'p' => array( t('Paragraphs'), "A single line break\nhas no effect.\n\nBut two line breaks start a new paragraph."),
|
'p' => array( t('Paragraphs'), "A single line break\nhas no effect.\n\nBut two line breaks start a new paragraph."),
|
||||||
'h2' => array( t('Headings'), '=='. t('Section') ."==\n".
|
'h2' => array( t('Headings'), '=='. t('Section') ."==\n".
|
||||||
'==='. t('Subsection') ."===\n".
|
'==='. t('Subsection') ."===\n".
|
||||||
'===='. t('Subsection two') ."===="),
|
'===='. t('Subsection two') ."===="),
|
||||||
'ul' => array( t('Unordered lists'), "* First list item\n* Second list item\n** A nested list item"),
|
'ul' => array( t('Unordered lists'), "* First list item\n* Second list item\n** A nested list item"),
|
||||||
'ol' => array( t('Ordered lists'), "# First list item\n# Second list item\n## A nested list item"),
|
'ol' => array( t('Ordered lists'), "# First list item\n# Second list item\n## A nested list item"),
|
||||||
'dl' => array( t('Definition lists'), ": A term\n; The defenition of that term\n; can span multiple lines\n: Another term\n; And another definition."),
|
'dl' => array( t('Definition lists'), ": A term\n; The defenition of that term\n; can span multiple lines\n: Another term\n; And another definition."),
|
||||||
'mix' => array( t('List types can be mixed'), "* A list\n*: Contains a definition \n*; It is both:\n*;# Inside that list, and\n*;# Correctly formated"),
|
'mix' => array( t('List types can be mixed'), "* A list\n*: Contains a definition \n*; It is both:\n*;# Inside that list, and\n*;# Correctly formated"),
|
||||||
'pre' => array( t('Preformated text'), " If you start with a space\n the formating is preserved"),
|
'pre' => array( t('Preformated text'), " If you start with a space\n the formating is preserved"),
|
||||||
'em' => array( t('Emphasis'), "''Emphasized text''"),
|
'em' => array( t('Emphasis'), "''Emphasized text''"),
|
||||||
'strong'=> array( t('Strong Emphasis'), "'''Strongly emphasized text'''"),
|
'strong'=> array( t('Strong Emphasis'), "'''Strongly emphasized text'''"),
|
||||||
);
|
);
|
||||||
$header = array(t('Description'), t('You Type'), t('You Get'));
|
$header = array(t('Description'), t('You Type'), t('You Get'));
|
||||||
foreach($tips as $tip) {
|
foreach($tips as $tip) {
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
array('data' => $tip[0], 'class' => 'description'),
|
array('data' => $tip[0], 'class' => 'description'),
|
||||||
array('data' => strpos($tip[1],"\n") !== false
|
array('data' => strpos($tip[1],"\n") !== false
|
||||||
? '<pre>'. check_plain($tip[1]) .'</pre>'
|
? '<pre>'. check_plain($tip[1]) .'</pre>'
|
||||||
: '<code>'. check_plain($tip[1]) .'</code>',
|
: '<code>'. check_plain($tip[1]) .'</code>',
|
||||||
'class' => 'type'),
|
'class' => 'type'),
|
||||||
array('data' => autoformat($tip[1]), 'class' => 'get')
|
array('data' => autoformat($tip[1]), 'class' => 'get')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$output = t('Automatic formating of text using the same tags as <a href="http://en.wikipedia.org/wiki/Wikipedia:How_to_edit_a_page#Wiki_markup">MediaWiki (wikipedia)</a>.');
|
$output = t('Automatic formating of text using the same tags as <a href="http://en.wikipedia.org/wiki/Wikipedia:How_to_edit_a_page#Wiki_markup">MediaWiki (wikipedia)</a>.');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Automatic formating of text using the same tags as MediaWiki (wikipedia).
|
// Automatic formating of text using the same tags as MediaWiki (wikipedia).
|
||||||
|
|
||||||
require_once('./modules/mse-drupal-modules/highlight.inc');
|
require_once('./modules/mse-drupal-modules/highlight.inc');
|
||||||
|
|
||||||
// quick and dirty aliasses
|
// quick and dirty aliasses
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ $built_in_functions = array(
|
|||||||
'filter_list' =>'',
|
'filter_list' =>'',
|
||||||
'random_shuffle' =>'',
|
'random_shuffle' =>'',
|
||||||
'random_select' =>'',
|
'random_select' =>'',
|
||||||
'random_select_many' =>'',
|
'random_select_many' =>'',
|
||||||
'get_card_styling' =>'',
|
'get_card_styling' =>'',
|
||||||
'get_card_stylesheet' =>'',
|
'get_card_stylesheet' =>'',
|
||||||
// keywords
|
// keywords
|
||||||
'expand_keywords' =>'', 'expand_keywords_rule'=>'expand_keywords',
|
'expand_keywords' =>'', 'expand_keywords_rule'=>'expand_keywords',
|
||||||
@@ -93,14 +93,19 @@ $built_in_functions = array(
|
|||||||
'flip_vertical' =>'',
|
'flip_vertical' =>'',
|
||||||
'rotate' =>'',
|
'rotate' =>'',
|
||||||
'drop_shadow' =>'',
|
'drop_shadow' =>'',
|
||||||
|
'insert_image' =>'',
|
||||||
|
'dimensions_of' =>'',
|
||||||
'symbol_variation' =>'',
|
'symbol_variation' =>'',
|
||||||
'import_image' =>'',
|
'import_image' =>'',
|
||||||
'built_in_image' =>'',
|
'built_in_image' =>'',
|
||||||
// cards
|
// cards
|
||||||
'new_card' =>'',
|
'new_card' =>'',
|
||||||
'add_card_to_set' =>'',
|
'has_link' =>'',
|
||||||
|
'get_card_from_link' =>'',
|
||||||
|
'get_card_from_uid' =>'',
|
||||||
'get_card_styling' =>'',
|
'get_card_styling' =>'',
|
||||||
'get_card_stylesheet' =>'',
|
'get_card_stylesheet' =>'',
|
||||||
|
'add_card_to_set' =>'',
|
||||||
// html export
|
// html export
|
||||||
'to_html' =>'',
|
'to_html' =>'',
|
||||||
'symbols_to_html' =>'',
|
'symbols_to_html' =>'',
|
||||||
@@ -111,6 +116,7 @@ $built_in_functions = array(
|
|||||||
'write_set_file' =>'',
|
'write_set_file' =>'',
|
||||||
// other
|
// other
|
||||||
'get_mse_version' =>'',
|
'get_mse_version' =>'',
|
||||||
|
'get_mse_locale' =>'',
|
||||||
'get_mse_path' =>'',
|
'get_mse_path' =>'',
|
||||||
'trace' =>'',
|
'trace' =>'',
|
||||||
'assert' =>'',
|
'assert' =>'',
|
||||||
@@ -248,4 +254,4 @@ function highlight_script_string($code) {
|
|||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
Reference in New Issue
Block a user