mcc2 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.autotest +23 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +3 -0
- data/Gemfile +13 -0
- data/History.txt +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +51 -0
- data/Rakefile +12 -0
- data/config/i18n-tasks.yml +193 -0
- data/exe/mcc2 +18 -0
- data/exe/mcc2-generate-preview +17 -0
- data/exe/mcc2print +6 -0
- data/lib/libguib16.rb +1620 -0
- data/lib/mcc2/advanced_data_edit_dlg.rb +139 -0
- data/lib/mcc2/cc_dialogbox.rb +52 -0
- data/lib/mcc2/constants.rb +154 -0
- data/lib/mcc2/dataman/base.rb +61 -0
- data/lib/mcc2/dataman/csv.rb +49 -0
- data/lib/mcc2/dataman/database.rb +8 -0
- data/lib/mcc2/dataman/dbf.rb +45 -0
- data/lib/mcc2/dataman/none.rb +25 -0
- data/lib/mcc2/dataview.rb +348 -0
- data/lib/mcc2/dataview_dlg.rb +232 -0
- data/lib/mcc2/debug_tools.rb +20 -0
- data/lib/mcc2/fx_colored_item.rb +101 -0
- data/lib/mcc2/generate_preview.rb +68 -0
- data/lib/mcc2/gui/advanced_data_edit_dlg.rbin +0 -0
- data/lib/mcc2/gui/dataview_dlg.pp +522 -0
- data/lib/mcc2/gui/layoutview_dlg.pp +5115 -0
- data/lib/mcc2/gui/mcc2_mainwin.pp +838 -0
- data/lib/mcc2/gui/picture_data_edit_dlg.rbin +0 -0
- data/lib/mcc2/gui/printerview_dlg.pp +3311 -0
- data/lib/mcc2/images/Image-Arrow-Left.gif +0 -0
- data/lib/mcc2/images/Image-Arrow-Right.gif +0 -0
- data/lib/mcc2/images/Image-FastArrowLeft.gif +0 -0
- data/lib/mcc2/images/Image-FastArrowRight.bmp +0 -0
- data/lib/mcc2/images/Image-FastArrowRight.gif +0 -0
- data/lib/mcc2/images/application-exit.png +0 -0
- data/lib/mcc2/images/copy.png +0 -0
- data/lib/mcc2/images/country_de.png +0 -0
- data/lib/mcc2/images/country_gb.png +0 -0
- data/lib/mcc2/images/country_rs.png +0 -0
- data/lib/mcc2/images/cut.png +0 -0
- data/lib/mcc2/images/distribute-horizontal-baseline.png +0 -0
- data/lib/mcc2/images/distribute-vertical-baseline.png +0 -0
- data/lib/mcc2/images/document-close.png +0 -0
- data/lib/mcc2/images/document-edit.png +0 -0
- data/lib/mcc2/images/document-new.png +0 -0
- data/lib/mcc2/images/document-open.png +0 -0
- data/lib/mcc2/images/document-print-frame.png +0 -0
- data/lib/mcc2/images/document-print.png +0 -0
- data/lib/mcc2/images/document-save-as.png +0 -0
- data/lib/mcc2/images/document-save.png +0 -0
- data/lib/mcc2/images/documentation.png +0 -0
- data/lib/mcc2/images/draw-rectangle.png +0 -0
- data/lib/mcc2/images/dummy.gif +0 -0
- data/lib/mcc2/images/exchange-positions.png +0 -0
- data/lib/mcc2/images/insert-image.png +0 -0
- data/lib/mcc2/images/insert-text.png +0 -0
- data/lib/mcc2/images/libreoffice-oasis-master-document.png +0 -0
- data/lib/mcc2/images/measure.png +0 -0
- data/lib/mcc2/images/messagebox_warning.png +0 -0
- data/lib/mcc2/images/paste.png +0 -0
- data/lib/mcc2/images/process-stop.png +0 -0
- data/lib/mcc2/images/zoom-in.png +0 -0
- data/lib/mcc2/layout.rb +323 -0
- data/lib/mcc2/layout_file.rb +794 -0
- data/lib/mcc2/layout_object/barcode.rb +33 -0
- data/lib/mcc2/layout_object/box.rb +18 -0
- data/lib/mcc2/layout_object/chip.rb +54 -0
- data/lib/mcc2/layout_object/embed.rb +16 -0
- data/lib/mcc2/layout_object/go_attribut.rb +16 -0
- data/lib/mcc2/layout_object/graphic.rb +59 -0
- data/lib/mcc2/layout_object/magstripe.rb +13 -0
- data/lib/mcc2/layout_object/picture.rb +22 -0
- data/lib/mcc2/layout_object/text.rb +29 -0
- data/lib/mcc2/layout_win.rb +2052 -0
- data/lib/mcc2/layoutview.rb +845 -0
- data/lib/mcc2/layoutview_dlg.rb +2058 -0
- data/lib/mcc2/locales.rb +27 -0
- data/lib/mcc2/mcc2_mainwin.rb +453 -0
- data/lib/mcc2/mcc2gui.rb +295 -0
- data/lib/mcc2/mcc2print.rb +54 -0
- data/lib/mcc2/picture_data_edit_dlg.rb +139 -0
- data/lib/mcc2/print_dlg.rb +520 -0
- data/lib/mcc2/printer/base.rb +148 -0
- data/lib/mcc2/printer/card_printer.rb +45 -0
- data/lib/mcc2/printer/file_printer.rb +135 -0
- data/lib/mcc2/printer/gdi_card_printer.rb +14 -0
- data/lib/mcc2/printer/gdi_printer.rb +197 -0
- data/lib/mcc2/printer/linux_cups_printer.rb +92 -0
- data/lib/mcc2/printer/preview.rb +277 -0
- data/lib/mcc2/printer/printer_cab.rb +118 -0
- data/lib/mcc2/printer/printer_cx320_direct.rb +286 -0
- data/lib/mcc2/printer/printer_epl.rb +118 -0
- data/lib/mcc2/printer/printer_ttp34x.rb +124 -0
- data/lib/mcc2/printer/printer_zebra.rb +324 -0
- data/lib/mcc2/printer/svg_drawer.rb +689 -0
- data/lib/mcc2/printerview.rb +604 -0
- data/lib/mcc2/printerview_dlg.rb +1248 -0
- data/lib/mcc2/version.rb +3 -0
- data/lib/mcc2.rb +11 -0
- data/locales/de.yml +6 -0
- data/locales/en.yml +502 -0
- data/locales/rs.yml +502 -0
- data/mcc2.gemspec +41 -0
- data/test/dummy.rb +19 -0
- data/test/layouts/bart_simpson.png +0 -0
- data/test/layouts/color_test.xml +151 -0
- data/test/layouts/ms.xml +67 -0
- data/test/ruby_print.rb +380 -0
- data/test/test.csv +4 -0
- data/test/test.dbf +0 -0
- data/test/test.str +4 -0
- data/test/test_mcc2.rb +8 -0
- data.tar.gz.sig +6 -0
- metadata +421 -0
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,794 @@
|
|
|
1
|
+
require "nokogiri" # für die Layout-Datei
|
|
2
|
+
require "mcc2/constants"
|
|
3
|
+
require "mcc2/layout_object/go_attribut"
|
|
4
|
+
require "mcc2/layout_object/graphic" # die Basisklasse für die grafischen Objekte
|
|
5
|
+
require "mcc2/layout_object/barcode" # grafische Barcode-Objekte
|
|
6
|
+
require "mcc2/layout_object/picture" # grafische Bild-Objekte
|
|
7
|
+
require "mcc2/layout_object/text" # grafische Text-Objekte
|
|
8
|
+
require "mcc2/layout_object/box"
|
|
9
|
+
require "mcc2/layout_object/magstripe"
|
|
10
|
+
require "mcc2/layout_object/chip"
|
|
11
|
+
require "mcc2/layout_object/embed"
|
|
12
|
+
|
|
13
|
+
module Mcc2
|
|
14
|
+
module Printer
|
|
15
|
+
autoload :GdiPrinter, "mcc2/printer/gdi_printer"
|
|
16
|
+
autoload :FilePrinter, "mcc2/printer/file_printer"
|
|
17
|
+
autoload :LinuxCupsPrinter, "mcc2/printer/linux_cups_printer"
|
|
18
|
+
autoload :PrinterZebra, "mcc2/printer/printer_zebra"
|
|
19
|
+
autoload :PrinterCab, "mcc2/printer/printer_cab"
|
|
20
|
+
autoload :PrinterEpl, "mcc2/printer/printer_epl"
|
|
21
|
+
autoload :PrinterCx320Direct, "mcc2/printer/printer_cx320_direct"
|
|
22
|
+
autoload :PrinterCx320Gdi, "mcc2/printer/printer_cx320_gdi"
|
|
23
|
+
autoload :PrinterTTP34x, "mcc2/printer/printer_ttp34x"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module DataMan
|
|
27
|
+
autoload :Database, "mcc2/dataman/database"
|
|
28
|
+
autoload :CSV, "mcc2/dataman/csv"
|
|
29
|
+
autoload :DBF, "mcc2/dataman/dbf"
|
|
30
|
+
autoload :None, "mcc2/dataman/none"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class LayoutFile
|
|
34
|
+
class Error < RuntimeError
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class WrongDataSourceEncoding < Error
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class WrongDataSourceType < Error
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class InvalidFileVersion < Error
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
FILE_VERSION_RANGE = 1..4
|
|
47
|
+
|
|
48
|
+
attr_accessor :attributes
|
|
49
|
+
attr_accessor :filename
|
|
50
|
+
attr_reader :warnings
|
|
51
|
+
attr_reader :xpath_changes
|
|
52
|
+
|
|
53
|
+
def self.load_from_xml(*args)
|
|
54
|
+
o = new
|
|
55
|
+
o.load_from_xml(*args)
|
|
56
|
+
o
|
|
57
|
+
end
|
|
58
|
+
#---------------------------------------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
def self.create_xml(*args)
|
|
61
|
+
o = new
|
|
62
|
+
o.create_xml(*args)
|
|
63
|
+
o
|
|
64
|
+
end
|
|
65
|
+
#---------------------------------------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
def initialize
|
|
68
|
+
@changed = true
|
|
69
|
+
@xml_doc = nil
|
|
70
|
+
@attributes = {}
|
|
71
|
+
add_attr(S_DUPLEX, String, false)
|
|
72
|
+
add_attr(S_FRONT_FLIP, String, false)
|
|
73
|
+
add_attr(S_FRONT_FLOP, String, false)
|
|
74
|
+
add_attr(S_BACK_FLIP, String, true)
|
|
75
|
+
add_attr(S_BACK_FLOP, String, true)
|
|
76
|
+
add_attr(S_WIDTH, Integer, LAYOUT_DEFAULT_WIDTH)
|
|
77
|
+
add_attr(S_HEIGHT, Integer, LAYOUT_DEFAULT_HEIGHT)
|
|
78
|
+
add_attr(S_X_OFFSET, Integer, LAYOUT_DEFAULT_X_OFFSET)
|
|
79
|
+
add_attr(S_Y_OFFSET, Integer, LAYOUT_DEFAULT_Y_OFFSET)
|
|
80
|
+
add_attr(S_BARCODE_DPI, Float, 203.2)
|
|
81
|
+
add_attr(S_DATASOURCE, String, "")
|
|
82
|
+
add_attr(S_DATASOURCETYP, String, NONE)
|
|
83
|
+
add_attr(S_DATASOURCEENCODING, String, ENC_UTF8)
|
|
84
|
+
add_attr(S_CONTACTLESS, String, false)
|
|
85
|
+
add_attr(S_CONTACT, String, false)
|
|
86
|
+
add_attr(S_MAGSTRIPE, String, false)
|
|
87
|
+
add_attr(S_PRINTERTYPE, String, "FilePrinter")
|
|
88
|
+
add_attr(S_FILEPRINTER_SAVE_AS, String, "./mcc2_%d_%p.jpeg")
|
|
89
|
+
add_attr(S_FILEPRINTER_DPI, Integer, 300)
|
|
90
|
+
add_attr(S_LINUX_CUPS_PRINTER, String, "")
|
|
91
|
+
add_attr(S_LINUX_CUPS_OPTIONS, String, '{"print-scaling":"none"}')
|
|
92
|
+
add_attr(S_LINUX_CUPS_DPI, Integer, 200)
|
|
93
|
+
add_attr(S_GDIPRINTER_NAME, String, "")
|
|
94
|
+
add_attr(S_GDIPRINTER_INITDATA, String, "")
|
|
95
|
+
add_attr(S_ZEBRAPRINTER_NAME, String, "")
|
|
96
|
+
add_attr(S_ZEBRAPRINTER_INITDATA, String, "")
|
|
97
|
+
add_attr(S_CABPRINTER_HOST, String, "localhost")
|
|
98
|
+
add_attr(S_CABPRINTER_PORT, Integer, 9100)
|
|
99
|
+
add_attr(S_CABPRINTER_DPI, Integer, 300)
|
|
100
|
+
add_attr(S_CABPRINTER_PAGE_COMMANDS, String,
|
|
101
|
+
'ePNG;*
|
|
102
|
+
dPNG;pngimg
|
|
103
|
+
\e.%IMAGE_DATA_PNG%\e.
|
|
104
|
+
mm
|
|
105
|
+
zO
|
|
106
|
+
J
|
|
107
|
+
H125,+0,T,R0
|
|
108
|
+
P0.00
|
|
109
|
+
O R
|
|
110
|
+
Sl1;0.0,0.00,%PAGE_HEIGHT%,%PAGE_HEIGHT%,%PAGE_WIDTH%
|
|
111
|
+
I:Field1;%PAGE_OFFSET_X%,%PAGE_OFFSET_Y%,0;pngimg
|
|
112
|
+
A1
|
|
113
|
+
')
|
|
114
|
+
add_attr(S_EPLPRINTER_DEVICE, String, "/dev/usb/lp0")
|
|
115
|
+
add_attr(S_EPLPRINTER_DPI, Integer, 203)
|
|
116
|
+
add_attr(S_EPLPRINTER_PAGE_COMMANDS, String,
|
|
117
|
+
'
|
|
118
|
+
OD
|
|
119
|
+
N
|
|
120
|
+
D8
|
|
121
|
+
S2
|
|
122
|
+
q%PAGE_WIDTH_PX%
|
|
123
|
+
GK"*"
|
|
124
|
+
GM"image1"%IMAGE_LEN_DATA_PCX%
|
|
125
|
+
O
|
|
126
|
+
JF
|
|
127
|
+
WN
|
|
128
|
+
ZB
|
|
129
|
+
GG%PAGE_OFFSET_X_PX%,%PAGE_OFFSET_Y_PX%,"image1"
|
|
130
|
+
P1
|
|
131
|
+
')
|
|
132
|
+
|
|
133
|
+
add_attr(S_TTP34XPRINTER_DEVICE, String, "/dev/usb/lp0")
|
|
134
|
+
add_attr(S_TTP34XPRINTER_DPI, Integer, 300)
|
|
135
|
+
add_attr(S_TTP34XPRINTER_PAGE_COMMANDS, String,
|
|
136
|
+
'SPEED 8 REM Wertebereich: 1-8
|
|
137
|
+
DENSITY 12 REM Wertebereich: 0-15
|
|
138
|
+
SIZE %PAGE_WIDTH_MM% mm,%PAGE_HEIGHT_MM% mm
|
|
139
|
+
CLS
|
|
140
|
+
DOWNLOAD "label.pcx",%IMAGE_LEN_DATA_PCX%
|
|
141
|
+
PUTPCX %PAGE_OFFSET_X_PX%,%PAGE_OFFSET_Y_PX%,"label.pcx"
|
|
142
|
+
PRINT 1
|
|
143
|
+
')
|
|
144
|
+
|
|
145
|
+
add_attr(S_CX320_DRIVER, String, "CX320_DLL")
|
|
146
|
+
add_attr(S_CX320_PRINTER_NR, Integer, 0)
|
|
147
|
+
add_attr(S_CX320_PARALLEL_PRINT, String, "second_card")
|
|
148
|
+
add_attr(S_CX320_CONFIG, String, "{}")
|
|
149
|
+
|
|
150
|
+
@warnings = []
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private def apply_xpath_changes(xpath_changes)
|
|
154
|
+
xpath_changes.each do |xpath, value|
|
|
155
|
+
if !(m = /^\{(?<filematch>.*)\}(?<xpath>.*)$/.match(xpath)) || (filename && File.fnmatch?(m[:filematch], File.basename(filename)))
|
|
156
|
+
change_first_xpath_value(m&.[](:xpath) || xpath, value)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
@xpath_changes = xpath_changes
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# erzeugt eine neue XML-Datei und initialisiert die entsprechenden Variablen und Objekte
|
|
163
|
+
def create_xml(filename, xpath_changes = {})
|
|
164
|
+
@filename = filename
|
|
165
|
+
@xml_doc = Nokogiri::XML::Document.new
|
|
166
|
+
@xml_doc.encoding = "UTF-8"
|
|
167
|
+
@xml_doc.root = Nokogiri::XML::Node.new(S_ROOT, @xml_doc)
|
|
168
|
+
|
|
169
|
+
# Layout definieren
|
|
170
|
+
@xml_doc.root << node = Nokogiri::XML::Node.new(S_LAYOUT, @xml_doc)
|
|
171
|
+
attributes.each_pair do |attr_name, attr|
|
|
172
|
+
n = Nokogiri::XML::Node.new(attr.attr_name, @xml_doc)
|
|
173
|
+
n.content = attr.attr_value.to_s
|
|
174
|
+
node << n
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Chip definieren
|
|
178
|
+
@xml_doc.root << node = Nokogiri::XML::Node.new(S_CHIP, @xml_doc)
|
|
179
|
+
(1..CHIPPARAM_FIELD_COUNT).each do |i|
|
|
180
|
+
node << Nokogiri::XML::Node.new("#{S_PARAM}_#{i}", @xml_doc)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Magstripe definieren
|
|
184
|
+
ensure_magsripe_attrs
|
|
185
|
+
|
|
186
|
+
# Container für die GraphikObjekte definieren definieren
|
|
187
|
+
@xml_doc.root << node = Nokogiri::XML::Node.new(GRAPHICOBJECTS, @xml_doc)
|
|
188
|
+
|
|
189
|
+
apply_xpath_changes(xpath_changes)
|
|
190
|
+
|
|
191
|
+
changed!
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# lädt das XML-File und initialisiert die entsprechenden Variablen und Objekte
|
|
195
|
+
# ==== Parameter
|
|
196
|
+
# +filename+:: der NAme des XML-Files in welchem die Layout-Spezifikation gespeichert werden soll
|
|
197
|
+
def load_from_xml(filename, xpath_changes = {})
|
|
198
|
+
return nil if filename == ""
|
|
199
|
+
|
|
200
|
+
@filename = filename
|
|
201
|
+
@changed = false
|
|
202
|
+
@xml_doc = File.open(filename) { |fd| Nokogiri::XML(fd) }
|
|
203
|
+
|
|
204
|
+
apply_xpath_changes(xpath_changes)
|
|
205
|
+
|
|
206
|
+
@xml_doc.root["version"] ||= "1"
|
|
207
|
+
filever = @xml_doc.root["version"].to_i
|
|
208
|
+
unless FILE_VERSION_RANGE.include?(filever)
|
|
209
|
+
raise InvalidFileVersion, I18n.t(:open_layout_version_error, default: "Die Datei %{filename} ist nach Version %{filever} aufgebaut, dieses Programm kann aber nur die Versionen %{supported} verarbeiten", filename: filename.inspect, filever: , supported: FILE_VERSION_RANGE.inspect)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
if filever == 1 && have_barcode_objects?
|
|
213
|
+
@warnings << I18n.t(:open_layout_old_barby, default: <<~EOT)
|
|
214
|
+
Diese Datei ist noch mit Barby-, statt den neueren Zint-Barcodes aufgebaut.
|
|
215
|
+
Daher müssen alle Barcodes geprüft und ggf. neu justiert werden!
|
|
216
|
+
Diese Warnung entfällt, sobald diese Datei einmal gespeichert wird.
|
|
217
|
+
EOT
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# ................................................................................................................................
|
|
221
|
+
# die allgemeine Layout-Einstellungen auslesen
|
|
222
|
+
|
|
223
|
+
# kontrollieren, ob alle Nodes des Layouts existieren, ansonsten anlegen und als 'changed' markieren
|
|
224
|
+
lay_attrs = @xml_doc.at_xpath("//#{S_ROOT}/#{S_LAYOUT}")
|
|
225
|
+
@attributes.each_pair do |attr_bez, attr|
|
|
226
|
+
element = lay_attrs.at_xpath(attr.attr_name)
|
|
227
|
+
unless element
|
|
228
|
+
n = Nokogiri::XML::Node.new(attr.attr_name, @xml_doc)
|
|
229
|
+
n.content = attr.attr_value.to_s
|
|
230
|
+
lay_attrs << n
|
|
231
|
+
changed!
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# kontrollieren, ob die Datenquelle eine gültige Angabe ist, wenn nicht, dann den Benutzer informieren und auf Standard setzen
|
|
236
|
+
check_valid_datasourcetyp
|
|
237
|
+
|
|
238
|
+
# wenn bei Datensourectyp nicht 'none' eingetrage ist, also eine Datenquelle verwendet wird
|
|
239
|
+
# kontrollieren, ob das eingestellte Encoding eine gültige Angabe ist, wenn nicht, dann den Benutzer informieren und auf Standard setzen
|
|
240
|
+
unless get_attr_value(S_DATASOURCETYP) == NONE
|
|
241
|
+
check_valid_encoding
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# ................................................................................................................................
|
|
245
|
+
# die Chip-Einstellungen auslesen
|
|
246
|
+
|
|
247
|
+
# kontrollieren, ob alle Nodes des Chips existieren, ansonsten als 'changed' markieren, da sie angelegt werden
|
|
248
|
+
chip_attrs = @xml_doc.at_xpath("//#{S_ROOT}/#{S_CHIP}")
|
|
249
|
+
(1..CHIPPARAM_FIELD_COUNT).each do |i|
|
|
250
|
+
attr_name = "#{S_PARAM}_#{i}"
|
|
251
|
+
element = chip_attrs.at_xpath(attr_name)
|
|
252
|
+
unless element
|
|
253
|
+
changed!
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Older files store chip params as array.
|
|
257
|
+
# Change them to hash form with the index as the key.
|
|
258
|
+
if filever < 3
|
|
259
|
+
param = element.content
|
|
260
|
+
if i == 8
|
|
261
|
+
if !param.to_s.empty?
|
|
262
|
+
if param =~ /^RUBY;(.*)/
|
|
263
|
+
param = "RubyJobFile=#{$1}"
|
|
264
|
+
set_attr_value(attr_name, param, S_CHIP)
|
|
265
|
+
else
|
|
266
|
+
raise InvalidScriptType, "invalid perso script: #{param.inspect}"
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
elsif i == 23
|
|
270
|
+
if !param.to_s.empty?
|
|
271
|
+
param = "OpenReader=#{param}"
|
|
272
|
+
set_attr_value(attr_name, param, S_CHIP)
|
|
273
|
+
end
|
|
274
|
+
elsif !param.to_s.empty?
|
|
275
|
+
param = "#{i}=#{param}"
|
|
276
|
+
set_attr_value(attr_name, param, S_CHIP)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Older files don't respect the bounding box of text objects
|
|
282
|
+
# and object's Y means the text baseline, not the bounding box.
|
|
283
|
+
if filever < 4
|
|
284
|
+
@warnings << I18n.t(:open_layout_old_text_box, default: <<~EOT)
|
|
285
|
+
Diese Datei ist noch mit Textobjekten ohne Beachtung der Rahmengröße gespeichert.
|
|
286
|
+
Die Rahmengröße der Textobjekte wurde nun automatisch auf den des Beispieltextes gesetzt.
|
|
287
|
+
Evtl. muss aber eine Anpassung für die variablen Daten erfolgen.
|
|
288
|
+
|
|
289
|
+
Bitte prüfen Sie, dass alle Texte an der richtigen Position stehen.
|
|
290
|
+
EOT
|
|
291
|
+
|
|
292
|
+
converter = Class.new(Printer::Base) do
|
|
293
|
+
include SvgDrawer
|
|
294
|
+
|
|
295
|
+
def pango_font_of(go)
|
|
296
|
+
font = go[GOA_FONT_TYP]
|
|
297
|
+
if font == "from_file"
|
|
298
|
+
font = go.layout_file.expand_path(go[GOA_FONT_FILE])
|
|
299
|
+
end
|
|
300
|
+
fontsize = go[GOA_FONT_HEIGHT].to_f
|
|
301
|
+
begin
|
|
302
|
+
font_info = get_font_info(font, go)
|
|
303
|
+
rescue Printer::Base::ResourceNotFoundError
|
|
304
|
+
# ignore font error in the migration because
|
|
305
|
+
# verification is requested from the user anyway
|
|
306
|
+
_key, font_info = font_map.first
|
|
307
|
+
end
|
|
308
|
+
get_pango_font(font_info, pt(fontsize))
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def get_text_sizes(go)
|
|
312
|
+
data = go[GOA_SAMPLE_DATA].to_s
|
|
313
|
+
if !data.empty?
|
|
314
|
+
pango_font = pango_font_of(go)
|
|
315
|
+
context = pango_font_map.create_context
|
|
316
|
+
layout = Pango::Layout.new(context)
|
|
317
|
+
layout.font_description = pango_font
|
|
318
|
+
layout.text = data # set the text to render
|
|
319
|
+
|
|
320
|
+
layout.pixel_size.map{|px| px_to_mm(px) }
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def get_new_coods(go)
|
|
325
|
+
x = go[GOA_X].to_f
|
|
326
|
+
y = go[GOA_Y].to_f
|
|
327
|
+
rotation = go[GOA_ROTATION].to_f
|
|
328
|
+
|
|
329
|
+
context = pango_font_map.create_context
|
|
330
|
+
pango_font = pango_font_of(go)
|
|
331
|
+
metrics = context.get_metrics(pango_font, Pango::Language.default)
|
|
332
|
+
|
|
333
|
+
descent = metrics.descent.to_f / Pango::SCALE
|
|
334
|
+
line_height = metrics.height.to_f / Pango::SCALE
|
|
335
|
+
rec = Printer::Base::Transformation.new(x, y).rotate(rotation).translate(0, -px_to_mm(line_height - descent))
|
|
336
|
+
return rec.x, rec.y
|
|
337
|
+
end
|
|
338
|
+
end.new
|
|
339
|
+
|
|
340
|
+
converter.add_fonts_from_layout(self)
|
|
341
|
+
|
|
342
|
+
# Remove "-" from font names, which was inserted by rmagick
|
|
343
|
+
sorted_id_list.each do |id|
|
|
344
|
+
go = find_graphic_object_by_id(id)
|
|
345
|
+
font = go[GOA_FONT_TYP]
|
|
346
|
+
if font && font != "from_file"
|
|
347
|
+
font = font.tr("-", " ")
|
|
348
|
+
set_object_by_ids([id], GOA_FONT_TYP, font)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Set a valid size in all text objects to the boinding box of the sample text
|
|
353
|
+
# and adjust X,Y position to the corner of the box.
|
|
354
|
+
sorted_id_list.each do |id|
|
|
355
|
+
go = find_graphic_object_by_id(id)
|
|
356
|
+
typ = go[GOA_TYP]
|
|
357
|
+
if typ == TEXTOBJECT
|
|
358
|
+
just = go[GOA_JUSTIFICATION]
|
|
359
|
+
just = just.sub("Links", "left")
|
|
360
|
+
.sub("Mitte", "mid")
|
|
361
|
+
.sub("Rechts", "right")
|
|
362
|
+
|
|
363
|
+
w, h = converter.get_text_sizes(go)
|
|
364
|
+
# set bounding box and keep a little bit of space for safty
|
|
365
|
+
if just == S_JUST_LEFT
|
|
366
|
+
# Don't change middle or right aligned, they should already be valid
|
|
367
|
+
set_object_by_ids([id], GOA_WIDTH, format("%0.2f", w * 1.1 + 5.0))
|
|
368
|
+
end
|
|
369
|
+
set_object_by_ids([id], GOA_HEIGHT, format("%0.2f", h * 1.1 + 1))
|
|
370
|
+
|
|
371
|
+
x, y = converter.get_new_coods(go)
|
|
372
|
+
# move text up, because old old Y means text baseline
|
|
373
|
+
# and new Y means upper left corner of the bounding box
|
|
374
|
+
set_object_by_ids([id], GOA_X, format("%0.2f", x))
|
|
375
|
+
set_object_by_ids([id], GOA_Y, format("%0.2f", y))
|
|
376
|
+
|
|
377
|
+
set_object_by_ids([id], GOA_JUSTIFICATION, just)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
ensure_magsripe_attrs
|
|
383
|
+
|
|
384
|
+
# ................................................................................................................................
|
|
385
|
+
# die Einstellungen der graphischen Objekte auslesen
|
|
386
|
+
|
|
387
|
+
# kontrollieren, ob alle Nodes der GraphicObjects existieren, ansonsten anlegen und als 'changed' markieren
|
|
388
|
+
@xml_doc.xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}/#{GRAPHICOBJECT}").each do |go_struct|
|
|
389
|
+
typ = go_struct.at_xpath(GOA_TYP).content
|
|
390
|
+
go = LayoutObject::Graphic.get_object_by_typ(typ)
|
|
391
|
+
go.go_attributes.each_pair do |go_attrname, go_attr|
|
|
392
|
+
element = go_struct.at_xpath(go_attr.attr_name)
|
|
393
|
+
unless element
|
|
394
|
+
n = Nokogiri::XML::Node.new(go_attr.attr_name, @xml_doc)
|
|
395
|
+
n.content = go_attr.attr_value.to_s
|
|
396
|
+
go_struct << n
|
|
397
|
+
changed!
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def ensure_magsripe_attrs
|
|
404
|
+
# ................................................................................................................................
|
|
405
|
+
# die Magnetstreifen-Einstellungen auslesen
|
|
406
|
+
|
|
407
|
+
# kontrollieren, ob alle Nodes des Magstripes existieren, ansonsten anlegen und als 'changed' markieren
|
|
408
|
+
# todo
|
|
409
|
+
node_lay = @xml_doc.at_xpath("//#{S_ROOT}")
|
|
410
|
+
node_ms = node_lay.at_xpath("//#{S_ROOT}//#{S_MAGSTRIPEPARAMS}")
|
|
411
|
+
unless node_ms
|
|
412
|
+
node_ms = Nokogiri::XML::Node.new(S_MAGSTRIPEPARAMS, @xml_doc)
|
|
413
|
+
node_lay << node_ms
|
|
414
|
+
changed!
|
|
415
|
+
end
|
|
416
|
+
unless node_ms.at_xpath(S_MSSPUR1)
|
|
417
|
+
node_ms << Nokogiri::XML::Node.new(S_MSSPUR1, @xml_doc)
|
|
418
|
+
changed!
|
|
419
|
+
end
|
|
420
|
+
unless node_ms.at_xpath(S_MSSPUR2)
|
|
421
|
+
node_ms << Nokogiri::XML::Node.new(S_MSSPUR2, @xml_doc)
|
|
422
|
+
changed!
|
|
423
|
+
end
|
|
424
|
+
unless node_ms.at_xpath(S_MSSPUR3)
|
|
425
|
+
node_ms << Nokogiri::XML::Node.new(S_MSSPUR3, @xml_doc)
|
|
426
|
+
changed!
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def have_barcode_objects?
|
|
431
|
+
sorted_id_list.find do |id|
|
|
432
|
+
go = find_graphic_object_by_id(id)
|
|
433
|
+
go[GOA_TYP] == BARCODEOBJECT
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def find_graphic_object_by_id(id)
|
|
438
|
+
go = get_objectnode_by_id(id)
|
|
439
|
+
typ = go.at_xpath(GOA_TYP).content
|
|
440
|
+
|
|
441
|
+
LayoutObject::Graphic.get_object_by_typ(typ, xml_elem: go, layout_file: self)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def magstripe_object
|
|
445
|
+
ms_node = @xml_doc.at_xpath("//#{S_ROOT}//#{S_MAGSTRIPEPARAMS}")
|
|
446
|
+
LayoutObject::Magstripe.new(ms_node)
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def chip_object
|
|
450
|
+
chip_attrs = @xml_doc.at_xpath("//#{S_ROOT}/#{S_CHIP}")
|
|
451
|
+
LayoutObject::Chip.new chip_attrs
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
# holt den Zweig mit den Einstellungen eines graphischen Objekts aus dem XML-File mit der Layout-Spezifikation
|
|
455
|
+
# ==== Parameter
|
|
456
|
+
# +id+:: die Nummer, unter welcher das Attribut gespeichert ist
|
|
457
|
+
private def get_objectnode_by_id(id)
|
|
458
|
+
@xml_doc.at_xpath("(//#{S_ROOT}/#{GRAPHICOBJECTS}/#{GRAPHICOBJECT})[#{id+1}]")
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def get_layers_of_page(page_nr)
|
|
462
|
+
@xml_doc.xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}/#{GRAPHICOBJECT}").select do |go_struct|
|
|
463
|
+
go_struct.at_xpath(GOA_PAGE_NR).content.to_i == page_nr
|
|
464
|
+
end.map do |go_struct|
|
|
465
|
+
go_struct.at_xpath(GOA_LAYER).content.to_i
|
|
466
|
+
end.uniq
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def get_object_by_id(obj_id, attr)
|
|
470
|
+
node = get_objectnode_by_id(obj_id)
|
|
471
|
+
node.at_xpath(attr).content if node
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
# return true - etwas verändert
|
|
475
|
+
# false - nichts verändert
|
|
476
|
+
def set_object_by_ids(obj_ids, attr, value)
|
|
477
|
+
ch = false
|
|
478
|
+
obj_ids.each do |obj_id|
|
|
479
|
+
node = get_objectnode_by_id(obj_id).at_xpath(attr)
|
|
480
|
+
|
|
481
|
+
# When multiple objects are selected -> ignore attributes not available for this object
|
|
482
|
+
next if !node && obj_ids.size > 1
|
|
483
|
+
|
|
484
|
+
value = value.to_s
|
|
485
|
+
if node.content != value
|
|
486
|
+
node.content = value
|
|
487
|
+
ch ||= changed!
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
ch
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
# Fügt ein Graphik-Objekt zur Layout-Definition hinzu
|
|
494
|
+
# ==== Parameter
|
|
495
|
+
# +typ+:: Typ (Text, Barcode oder Bild)
|
|
496
|
+
# ==== Return
|
|
497
|
+
# Object [XML-Node]
|
|
498
|
+
def add_object(typ)
|
|
499
|
+
o = LayoutObject::Graphic.get_object_by_typ(typ)
|
|
500
|
+
id = get_new_id
|
|
501
|
+
node = @xml_doc.at_xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}")
|
|
502
|
+
go = Nokogiri::XML::Node.new(GRAPHICOBJECT, @xml_doc)
|
|
503
|
+
node << go
|
|
504
|
+
n = Nokogiri::XML::Node.new(GOA_TYP, @xml_doc)
|
|
505
|
+
n.content = typ
|
|
506
|
+
go << n
|
|
507
|
+
n = Nokogiri::XML::Node.new(GOA_ID, @xml_doc)
|
|
508
|
+
n.content = id.to_s
|
|
509
|
+
go << n
|
|
510
|
+
n = Nokogiri::XML::Node.new(GOA_NAME, @xml_doc)
|
|
511
|
+
n.content = "#{typ}##{id}"
|
|
512
|
+
go << n
|
|
513
|
+
o.go_attributes.each_pair do |goa_name, go_attribute|
|
|
514
|
+
unless [GOA_TYP, GOA_NAME].include?(go_attribute.attr_name)
|
|
515
|
+
n = Nokogiri::XML::Node.new(go_attribute.attr_name, @xml_doc)
|
|
516
|
+
n.content = go_attribute.attr_value.to_s
|
|
517
|
+
go << n
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
changed!
|
|
521
|
+
|
|
522
|
+
LayoutObject::Graphic.get_object_by_typ(typ, xml_elem: go, layout_file: self)
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
# ermittelt die nächst höhere ID (beeinflusst die Darstellungsebene)
|
|
526
|
+
def get_new_id
|
|
527
|
+
@xml_doc.xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}/#{GRAPHICOBJECT}").size
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
# liest die ID's der graphischen Objekte aus der Layout-Definition (XML) aus und
|
|
531
|
+
# sortiert sie
|
|
532
|
+
# ==== Return
|
|
533
|
+
# die sortierte Liste mit ID's [Array]
|
|
534
|
+
def sorted_id_list
|
|
535
|
+
@xml_doc.xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}/#{GRAPHICOBJECT}").size.times.to_a
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
# Reindex the objects according to the passed array of obj_ids
|
|
539
|
+
def reorder_id_list(obj_ids)
|
|
540
|
+
# Die ID's im XML entsprechend des ARRAY-Indexes über die alte ID setzen (ist automatisch eine Re-Indizierung zum Entfernen von Löschern.
|
|
541
|
+
# Dabei alle Objekte durchlaufen und im Array die Position der alten ID suchen und in die ID schreiben.
|
|
542
|
+
# Dies muss so getan werden.
|
|
543
|
+
# Wenn es anders herum versucht wird, d.h. das Array durchlaufen und dann das Objekt im XML gesucht, dann werden die ID's schon verändert und die Suche schlägt dann fehl.
|
|
544
|
+
base = @xml_doc.at_xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}")
|
|
545
|
+
elements = base.elements
|
|
546
|
+
obj_ids.each do |id|
|
|
547
|
+
elements[id].parent = base
|
|
548
|
+
end
|
|
549
|
+
changed!
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
# ermittelt den Inhalt eines Attributes des Layout-Abschnittes
|
|
553
|
+
# ==== Return
|
|
554
|
+
# den Inhalt des Attributes [String]
|
|
555
|
+
# ==== Parameter
|
|
556
|
+
# +attr_name+:: der Name des Attributes z.Bsp. 'datasource' Bitte vorwiegend Konstanten verwenden z. Bsp. S_DATASOURCE [String]
|
|
557
|
+
def get_attr_value(attr_name, base = S_LAYOUT)
|
|
558
|
+
lay_attrs = @xml_doc.at_xpath("//#{S_ROOT}/#{base}")
|
|
559
|
+
attr = lay_attrs.at_xpath(attr_name)
|
|
560
|
+
attr&.content
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
# setzt den Inhalt eines Attributes des Layout-Abschnittes
|
|
564
|
+
# ==== Return
|
|
565
|
+
# true wenn erfolgreich geändert
|
|
566
|
+
# false wenn keine Änderung
|
|
567
|
+
# ==== Parameter
|
|
568
|
+
# +attr_name+:: der Name des Attributes z.Bsp. 'datasource' Bitte vorwiegend Konstanten verwenden z. Bsp. S_DATASOURCE [String]
|
|
569
|
+
# +value+:: der Wert der geschrieben werden soll [String]
|
|
570
|
+
def set_attr_value(attr_name, value, base = S_LAYOUT)
|
|
571
|
+
lay_attrs = @xml_doc.at_xpath("//#{S_ROOT}/#{base}")
|
|
572
|
+
attr = lay_attrs.at_xpath(attr_name)
|
|
573
|
+
value = value.to_s
|
|
574
|
+
if attr.content != value
|
|
575
|
+
attr.content = value
|
|
576
|
+
changed!
|
|
577
|
+
else
|
|
578
|
+
false
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
# fügt ein neues Atrtribut zur Liste der Attribute (@attributes) hinzu
|
|
583
|
+
# ==== Parameter
|
|
584
|
+
# +name+:: der Name, den das Attribut erhalten soll
|
|
585
|
+
# +typ+:: der Typ
|
|
586
|
+
# +default+:: der Wert, mit dem das Attribut vorinitialisiert werden soll
|
|
587
|
+
def add_attr(name, typ, default)
|
|
588
|
+
attr = LayoutObject::GO_Attribut.new(name, typ, default)
|
|
589
|
+
@attributes[attr.attr_name] = attr
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
def change_first_xpath_value(xpath, value)
|
|
593
|
+
attr = @xml_doc.at_xpath(xpath)
|
|
594
|
+
raise I18n.t(:set_xpath_no_element_error, default: "Kein Element unter XPath %{xpath} in Datei %{filename} gefunden", xpath: xpath.inspect, filename: @filename) unless attr
|
|
595
|
+
puts I18n.t(:set_xpath_element, default: "Setze Element unter XPath %{xpath} in Datei %{filename} auf %{value}", xpath: xpath.inspect, filename: @filename, value: value.inspect)
|
|
596
|
+
if attr.content != value
|
|
597
|
+
attr.content = value
|
|
598
|
+
changed!
|
|
599
|
+
else
|
|
600
|
+
false
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
def save
|
|
605
|
+
# IDs sequenziell nummerieren für Kompatibilität mit älteren mcc2
|
|
606
|
+
@xml_doc.xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}/#{GRAPHICOBJECT}").each_with_index do |go_struct, idx|
|
|
607
|
+
go_struct.at_xpath(GOA_ID).content = idx
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
@xml_doc.root["version"] = FILE_VERSION_RANGE.last.to_s
|
|
611
|
+
File.open(@filename, "w") do |fd|
|
|
612
|
+
@xml_doc.write_to(fd, indent: 2)
|
|
613
|
+
end
|
|
614
|
+
@changed = false
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
# überprüft, ob der Wert Datasourcetyp in der Layoutdefinition ein gültiger Wert ist.
|
|
618
|
+
# Wenn nicht, wird ein Fehlerdialog angezeigt und der Standardwert gesetzt und das changed-Flag gesetzt
|
|
619
|
+
def check_valid_datasourcetyp
|
|
620
|
+
datasourcetyp = get_attr_value(S_DATASOURCETYP)
|
|
621
|
+
unless DataMan.valid_datasourcetyp?(datasourcetyp)
|
|
622
|
+
default = @attributes[S_DATASOURCETYP].attr_value
|
|
623
|
+
set_attr_value(S_DATASOURCETYP, default)
|
|
624
|
+
raise WrongDataSourceType, I18n.t(:open_layout_invalid_datasource_type, default: <<~EOTXT, datasourcetyp:, valid_types: VALID_DATASOURCES.join("', '"), new: default )
|
|
625
|
+
Der eingestellte Datenquellentyp '%{datasourcetyp}' ist ungültig.
|
|
626
|
+
|
|
627
|
+
Gültige Werte sind '%{valid_types}'.
|
|
628
|
+
|
|
629
|
+
Der Wert wird jetzt auf den Standardwert '%{new}' gesetzt.
|
|
630
|
+
|
|
631
|
+
Bitte stellen Sie in den Layouteigenschaften den korrekten Datenquellentyp
|
|
632
|
+
ein und speichern Sie die Einstellungen.
|
|
633
|
+
EOTXT
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# überprüft, ob der Wert Datasourcencoding in der Layoutdefinition ein gültiger Wert ist.
|
|
638
|
+
# Wenn nicht, wird ein Fehlerdialog angezeigt und der Standardwert gesetzt und das changed-Flag gesetzt
|
|
639
|
+
def check_valid_encoding
|
|
640
|
+
datasource_encoding = get_attr_value(S_DATASOURCEENCODING)
|
|
641
|
+
unless DataMan.valid_datasource_encoding?(datasource_encoding)
|
|
642
|
+
default = "UTF-8"
|
|
643
|
+
set_attr_value(S_DATASOURCEENCODING, default)
|
|
644
|
+
raise WrongDataSourceEncoding, I18n.t(:open_layout_invalid_datasource_encoding, default: <<-EOTXT, datasource_encoding:, valid_encodings: VALID_ENCODINGS.join("', '"))
|
|
645
|
+
Das eingestellte Encoding der Datenquelle '%{datasource_encoding}' ist ungültig.
|
|
646
|
+
|
|
647
|
+
Gültige Werte sind '%{valid_encodings}'.
|
|
648
|
+
|
|
649
|
+
Bitte stellen Sie in den Layouteigenschaften das korrekte Encoding
|
|
650
|
+
ein und speichern Sie die Einstellungen.
|
|
651
|
+
EOTXT
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
#---------------------------------------------------------------------------------------------------------
|
|
655
|
+
|
|
656
|
+
# ersetllt ein neues Graphik-Objekt und kopiert alle Attributte des übergebenen, außer ID, Typ und Name
|
|
657
|
+
# ==== Parameter
|
|
658
|
+
# +node+:: die XML-Node des zu kopierenden Objekts, fals nil übergeben wurde, kehrt die Methode unverrichteter Dinge zurück
|
|
659
|
+
def copy_objects(ids)
|
|
660
|
+
ids.each do |id|
|
|
661
|
+
obj = find_graphic_object_by_id(id)
|
|
662
|
+
|
|
663
|
+
o = add_object(obj[GOA_TYP])
|
|
664
|
+
obj.attributes.each do |attr|
|
|
665
|
+
# alle Attribute, außer Typ und Name kopieren, sofern sie vorhanden, ansonsten den Standard lassen
|
|
666
|
+
unless [GOA_TYP, GOA_NAME].include?(attr)
|
|
667
|
+
o[attr] = obj[attr]
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
end
|
|
671
|
+
changed!
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
def clipboard_copy(ids)
|
|
675
|
+
ids.map do |id|
|
|
676
|
+
get_objectnode_by_id(id).to_xml
|
|
677
|
+
end.join("\n")
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
def clipboard_cut(ids)
|
|
681
|
+
xml = clipboard_copy(ids)
|
|
682
|
+
changed = delete_objects(ids)
|
|
683
|
+
return xml, changed
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
def clipboard_paste(xml_data, after_id:)
|
|
687
|
+
frag = Nokogiri::XML.fragment(xml_data)
|
|
688
|
+
num_elements = frag.elements.size
|
|
689
|
+
if after_id
|
|
690
|
+
node = get_objectnode_by_id(after_id)
|
|
691
|
+
if node
|
|
692
|
+
node.add_next_sibling(frag)
|
|
693
|
+
else
|
|
694
|
+
node = @xml_doc.at_xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}")
|
|
695
|
+
node.prepend_child(frag)
|
|
696
|
+
end
|
|
697
|
+
else
|
|
698
|
+
node = @xml_doc.at_xpath("//#{S_ROOT}/#{GRAPHICOBJECTS}")
|
|
699
|
+
after_id = node.elements.size - 1
|
|
700
|
+
node << frag
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
changed! if num_elements > 0
|
|
704
|
+
num_elements.times.map {|t| after_id ? t + after_id + 1 : t }
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
# löscht sie übergebene XML-Node aus dem Layout ohne Rückfrage, diese muss in der aufrufenden Methode durchgeführt werden
|
|
708
|
+
# ==== Parameter
|
|
709
|
+
def delete_objects(ids)
|
|
710
|
+
changed = false
|
|
711
|
+
ids.sort.reverse.each do |id|
|
|
712
|
+
obj = find_graphic_object_by_id(id)
|
|
713
|
+
obj.delete
|
|
714
|
+
changed = true
|
|
715
|
+
end
|
|
716
|
+
changed! if changed
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
def build_printer_instance
|
|
720
|
+
printertype = get_attr_value(S_PRINTERTYPE)
|
|
721
|
+
printerclass = Printer.const_get(printertype)
|
|
722
|
+
printerclass.new
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
def build_dataman_instance
|
|
726
|
+
datamantyp = get_attr_value(S_DATASOURCETYP)
|
|
727
|
+
datasource = get_attr_value(S_DATASOURCE)
|
|
728
|
+
encoding = get_attr_value(S_DATASOURCEENCODING)
|
|
729
|
+
# Ruby-1.9 kennt kein LATIN1
|
|
730
|
+
encoding = "iso-8859-1" if /latin1/i.match?(encoding)
|
|
731
|
+
|
|
732
|
+
if datamantyp == DATABASE
|
|
733
|
+
DataMan::Database.new(datasource)
|
|
734
|
+
elsif datamantyp == CSV
|
|
735
|
+
datasource = expand_path(datasource)
|
|
736
|
+
DataMan::CSV.new(datasource, encoding)
|
|
737
|
+
elsif datamantyp == DBF
|
|
738
|
+
datasource = expand_path(datasource)
|
|
739
|
+
DataMan::DBF.new(datasource, encoding)
|
|
740
|
+
elsif datamantyp == NONE
|
|
741
|
+
DataMan::None.new(datasource)
|
|
742
|
+
else
|
|
743
|
+
raise "invalid type of datasource #{datamantyp.inspect}"
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
def build_chip_instance
|
|
748
|
+
if get_attr_value(S_CONTACTLESS) == S_TRUE || get_attr_value(S_CONTACT) == S_TRUE
|
|
749
|
+
chip_object
|
|
750
|
+
end
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
def get_binary_attr(attr)
|
|
754
|
+
initdatahex = get_attr_value(attr)
|
|
755
|
+
if initdatahex && !initdatahex.empty?
|
|
756
|
+
[initdatahex].pack("H*")
|
|
757
|
+
end
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
def set_binary_attr(attr, bindata)
|
|
761
|
+
set_attr_value(attr, bindata.unpack1("H*"))
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def expand_path(path)
|
|
765
|
+
path = path.gsub("%D", File.dirname(File.expand_path(@filename))) if @filename
|
|
766
|
+
path = path.gsub("%F", File.basename(@filename, ".*")) if @filename
|
|
767
|
+
pa = File.expand_path(path)
|
|
768
|
+
pa += "/" if path.end_with?("/")
|
|
769
|
+
pa
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
def shrink_path(path)
|
|
773
|
+
path = path.tr("\\", "/")
|
|
774
|
+
if @filename
|
|
775
|
+
path = path.sub(File.dirname(File.expand_path(@filename)), "%D")
|
|
776
|
+
end
|
|
777
|
+
if pwd = Dir.pwd
|
|
778
|
+
path = path.sub(pwd + "/", "")
|
|
779
|
+
end
|
|
780
|
+
if home = Dir.home
|
|
781
|
+
path = path.sub(home + "/", "~/")
|
|
782
|
+
end
|
|
783
|
+
path
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
def changed?
|
|
787
|
+
@changed
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
def changed!
|
|
791
|
+
@changed = true
|
|
792
|
+
end
|
|
793
|
+
end
|
|
794
|
+
end
|