ifmapper 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.txt CHANGED
@@ -1,8 +1,12 @@
1
+ v1.1.1 Improvements:
2
+ - Added support for Trizbort maps for reading and writing.
3
+ - Made failed connections turn cyan upon selection.
4
+
1
5
  v1.1.0 - Bug fixed select all so it can be done with keyboard.
2
6
 
3
7
  v1.0.9 - Bug fixed crash of cut selection when stubs were present.
4
8
  - Added option to automap rooms with all caps.
5
- - Bug fixed Select All rooms to show the selection.
9
+ - Bug fixed Select All/None rooms to show the selection.
6
10
 
7
11
  v1.0.8 - Added option to load a map from command-line.
8
12
  - Bug fixed pdf output of letters near exits.
data/IFMapper.gemspec CHANGED
@@ -2,7 +2,7 @@ require "rubygems"
2
2
 
3
3
  spec = Gem::Specification.new do |spec|
4
4
  spec.name = "ifmapper"
5
- spec.version = '1.1.0'
5
+ spec.version = '1.1.1'
6
6
  spec.author = "Gonzalo Garramuno"
7
7
  spec.email = 'ggarra13@gmail.com'
8
8
  spec.homepage = 'http://www.rubyforge.org/projects/ifmapper/'
@@ -122,7 +122,11 @@ class FXConnection < Connection
122
122
  #
123
123
  def draw(dc, zoom, opt)
124
124
  if @selected
125
- dc.foreground = 'yellow'
125
+ if @failed
126
+ dc.foreground = 'cyan'
127
+ else
128
+ dc.foreground = 'yellow'
129
+ end
126
130
  elsif @failed
127
131
  dc.foreground = 'red'
128
132
  else
@@ -2116,10 +2116,19 @@ class FXMap < Map
2116
2116
  #
2117
2117
  def export_inform7(file)
2118
2118
  require 'IFMapper/Inform7Writer'
2119
- file.sub!(/.inform$/, '')
2119
+ file.sub!(/\.inform$/, '')
2120
2120
  Inform7Writer.new(self, file)
2121
2121
  end
2122
2122
 
2123
+ #
2124
+ # Export map as a set of Inform source code files
2125
+ #
2126
+ def export_trizbort(file)
2127
+ require 'IFMapper/TrizbortWriter'
2128
+ file.sub!(/\.trizbort$/, '')
2129
+ TrizbortWriter.new(self, file)
2130
+ end
2131
+
2123
2132
  #
2124
2133
  # Export map as a set of Inform source code files
2125
2134
  #
@@ -2153,6 +2162,8 @@ class FXMap < Map
2153
2162
  export_ifm(file)
2154
2163
  when /\.t$/
2155
2164
  export_tads(file)
2165
+ when /\.trizbort$/
2166
+ export_trizbort(file)
2156
2167
  else
2157
2168
  @filename = file
2158
2169
  return _save
@@ -8,12 +8,12 @@ class FXMapFileDialog < FXFileDialog
8
8
  @@last_path = nil
9
9
 
10
10
  KNOWN_LOAD_EXTENSIONS = [
11
- "#{EXT_MAP_FILES} (*.map,*.gmp,*.ifm,*.inf,*.t,*.t3m)",
11
+ "#{EXT_MAP_FILES} (*.map,*.gmp,*.ifm,*.inf,*.t,*.t3m,*.trizbort)",
12
12
  EXT_ALL_FILES,
13
13
  ]
14
14
 
15
15
  KNOWN_SAVE_EXTENSIONS = [
16
- "#{EXT_MAP_FILES} (*.map,*.gmp,*.ifm,*.inf,*.inform,*.t,*.t3m)",
16
+ "#{EXT_MAP_FILES} (*.map,*.gmp,*.ifm,*.inf,*.inform,*.t,*.t3m,*.trizbort)",
17
17
  EXT_ALL_FILES,
18
18
  ]
19
19
 
@@ -46,7 +46,7 @@ require 'IFMapper/FXWarningBox'
46
46
  class FXMapperWindow < FXMainWindow
47
47
 
48
48
  PROGRAM_NAME = "Interactive Fiction Mapper"
49
- VERSION = '1.1.0'
49
+ VERSION = '1.1.1'
50
50
  AUTHOR = "Gonzalo Garramuño"
51
51
 
52
52
  @@copy_buffer = nil
@@ -98,7 +98,7 @@ class FXMapperWindow < FXMainWindow
98
98
  begin
99
99
  TADSReader.new(file, map)
100
100
  rescue => e
101
- return "#{e}"
101
+ return "#{e} #{e.backtrace}"
102
102
  end
103
103
  return map
104
104
  end
@@ -108,7 +108,7 @@ class FXMapperWindow < FXMainWindow
108
108
  begin
109
109
  InformReader.new(file, map)
110
110
  rescue => e
111
- return "#{e}"
111
+ return "#{e} #{e.backtrace}"
112
112
  end
113
113
  return map
114
114
  end
@@ -118,7 +118,17 @@ class FXMapperWindow < FXMainWindow
118
118
  begin
119
119
  GUEReader.new(file, map)
120
120
  rescue => e
121
- return "#{e}"
121
+ return "#{e} #{e.backtrace}"
122
+ end
123
+ return map
124
+ end
125
+
126
+ def open_trizbort(file, map)
127
+ require 'IFMapper/TrizbortReader'
128
+ begin
129
+ TrizbortReader.new(file, map)
130
+ rescue => e
131
+ return "#{e} #{e.backtrace}"
122
132
  end
123
133
  return map
124
134
  end
@@ -202,6 +212,8 @@ class FXMapperWindow < FXMainWindow
202
212
  tmp = open_tads(file, map)
203
213
  elsif file =~ /\.gmp$/
204
214
  tmp = open_guemap(file, map)
215
+ elsif file =~ /\.trizbort$/
216
+ tmp = open_trizbort(file, map)
205
217
  else
206
218
  tmp = open_map(file)
207
219
  end
@@ -395,6 +407,21 @@ class FXMapperWindow < FXMainWindow
395
407
  map.export_ifm(d.filename) if d.filename != ''
396
408
  end
397
409
 
410
+ #
411
+ # Export current map as an IFM file
412
+ #
413
+ def trizbort_export_cb(sender, sel, msg)
414
+ map = current_map
415
+ return unless map
416
+
417
+ require 'IFMapper/FXMapFileDialog'
418
+ d = FXMapFileDialog.new(self, MSG_SAVE_MAP_AS_TRIZBORT,
419
+ [
420
+ FMT_TRIZBORT
421
+ ])
422
+ map.export_trizbort(d.filename) if d.filename != ''
423
+ end
424
+
398
425
  #
399
426
  # Export current map as an Inform source file
400
427
  #
@@ -952,6 +979,9 @@ class FXMapperWindow < FXMainWindow
952
979
  cmd = FXMenuCommand.new(submenu, MENU_EXPORT_PDF, nil)
953
980
  cmd.connect(SEL_COMMAND, method(:pdf_export_cb))
954
981
 
982
+ cmd = FXMenuCommand.new(submenu, MENU_EXPORT_TRIZBORT, nil)
983
+ cmd.connect(SEL_COMMAND, method(:trizbort_export_cb))
984
+
955
985
  cmd = FXMenuCommand.new(submenu, MENU_EXPORT_IFM, nil)
956
986
  cmd.connect(SEL_COMMAND, method(:ifm_export_cb))
957
987
 
@@ -30,4 +30,10 @@ class FXSection < Section
30
30
  @win.copy_from(self)
31
31
  @win.show
32
32
  end
33
+
34
+ def initialize()
35
+ super
36
+ @win = nil
37
+ end
38
+
33
39
  end
@@ -1200,7 +1200,7 @@ class TranscriptReader
1200
1200
  debug "*** CANNOT AUTOMAP --- MAZE ***"
1201
1201
  dir = Room::DIRECTIONS[dir]
1202
1202
  @map.cannot_automap "Maze detected.\n'#{from}' #{dir} leads to '#{c.roomB}',\nnot to this '#{to}'."
1203
- # self.stop
1203
+ self.stop
1204
1204
  return nil
1205
1205
  end
1206
1206
  end
@@ -0,0 +1,259 @@
1
+ #
2
+ # Trizbort map reader
3
+ #
4
+
5
+ class FXMap; end
6
+
7
+ require 'rexml/document'
8
+ require 'IFMapper/FXConnection'
9
+
10
+ #
11
+ # Class that allows importing a Trizbort map file.
12
+ #
13
+ class TrizbortReader
14
+
15
+ class ParseError < StandardError; end
16
+ class MapError < StandardError; end
17
+
18
+
19
+
20
+ DIRS = {
21
+ 'n' => 0, # n
22
+ 's' => 4, # s
23
+ 'e' => 2, # e
24
+ 'w' => 6, # w
25
+ 'ne' => 1, # ne
26
+ 'nw' => 7, # nw
27
+ 'se' => 3, # se
28
+ 'sw' => 5, # sw
29
+
30
+ # Trizbort also support connections to the sides of centers
31
+ #
32
+ # --*--*--
33
+ # * *
34
+ # * *
35
+ # --*--*--
36
+ #
37
+ # We translate these as corner connections.
38
+ #
39
+ 'ene' => [2, 1], # ----*-
40
+ 'ese' => [2, 3], # ----*-
41
+ 'nne' => [0, 1],
42
+ 'wnw' => [6, 7],
43
+ 'wsw' => [6, 5],
44
+ 'nnw' => [0, 7],
45
+ 'ssw' => [4, 5],
46
+ }
47
+
48
+
49
+ attr :doc
50
+
51
+ @@debug = nil
52
+
53
+ def debug(x)
54
+ if @@debug.to_i > 0
55
+ $stderr.puts x
56
+ end
57
+ end
58
+
59
+ #
60
+ # Read Trimap rexml from file stream
61
+ #
62
+ def parse
63
+
64
+ rooms = {}
65
+
66
+
67
+ @doc.elements.each('trizbort/info/title') { |e|
68
+ @map.name = e.text
69
+ }
70
+
71
+ @doc.elements.each('trizbort/info/author') { |e|
72
+ @map.creator = e.text
73
+ }
74
+
75
+ @doc.elements.each('trizbort/map/room') { |e|
76
+ id = e.attributes['id'].to_i
77
+ name = e.attributes['name']
78
+ x = e.attributes['x'].to_i
79
+ y = e.attributes['y'].to_i
80
+ w = e.attributes['w'].to_i
81
+ h = e.attributes['h'].to_i
82
+ r = @map.new_room(x, y)
83
+ r.name = name
84
+ rooms[id] = r
85
+ e.elements.each('objects') { |o|
86
+ r.objects = o.text.to_s.gsub('|',"\n")
87
+ }
88
+ }
89
+
90
+ @doc.elements.each('trizbort/map/line') { |e|
91
+ style = e.attributes['style'].to_s
92
+
93
+ if style == 'dashed'
94
+ style = Connection::SPECIAL
95
+ else
96
+ style = Connection::FREE
97
+ end
98
+
99
+ id = e.attributes['id'].to_i
100
+ flow = e.attributes['flow']
101
+
102
+ if flow == 'oneWay'
103
+ flow = Connection::AtoB
104
+ else
105
+ flow = Connection::BOTH
106
+ end
107
+
108
+ startText = e.attributes['startText'].to_s
109
+ endText = e.attributes['endText'].to_s
110
+
111
+ line = {}
112
+
113
+ e.elements.each { |x|
114
+ name = x.local_name
115
+ if name == 'dock'
116
+ port = x.attributes['port']
117
+ room = x.attributes['id'].to_i
118
+ index = x.attributes['index'].to_i
119
+ line[index] = [port, rooms[room]]
120
+ elsif name == 'point'
121
+ index = x.attributes['index'].to_i
122
+ line[index] = [nil, nil]
123
+ end
124
+ }
125
+
126
+ if line.size > 0
127
+ roomA = line[0][1]
128
+ dirA = DIRS[line[0][0]]
129
+
130
+ if dirA.kind_of?(Array)
131
+ dirA.each { |d|
132
+ next if roomA[d]
133
+ dirA = d
134
+ break
135
+ }
136
+ if dirA.kind_of? Array
137
+ dirA = dirA[0]
138
+ end
139
+ end
140
+
141
+ if line.size > 1
142
+ roomB = line[1][1]
143
+ dirB = DIRS[line[1][0]]
144
+
145
+ if dirB.kind_of? Array
146
+ dirB.each { |d|
147
+ next if roomB[d]
148
+ dirB = d
149
+ break
150
+ }
151
+ if dirB.kind_of?(Array)
152
+ dirB = dirB[0]
153
+ end
154
+ end
155
+ end
156
+
157
+ debug "Connect: #{roomA} ->#{roomB} "
158
+ debug "dirA: #{dirA} dirB: #{dirB}"
159
+
160
+ if startText =~ /up?/i
161
+ startText = 1
162
+ elsif startText =~ /d(?:own)?/i
163
+ startText = 2
164
+ elsif startText =~ /in?/i
165
+ startText = 3
166
+ elsif startText =~ /o(?:ut)?/i
167
+ startText = 4
168
+ else
169
+ startText = 0
170
+ end
171
+
172
+ if endText =~ /up?/i
173
+ endText = 1
174
+ elsif endText =~ /d(?:own)?/i
175
+ endText = 2
176
+ elsif endText =~ /in?/i
177
+ endText = 3
178
+ elsif endText =~ /o(?:ut)?/i
179
+ endText = 4
180
+ else
181
+ endText = 0
182
+ end
183
+
184
+ debug "exitA: #{startText} exitB: #{endText}"
185
+
186
+ begin
187
+ c = @map.new_connection( roomA, dirA, roomB, dirB )
188
+ c.exitAtext = startText
189
+ if roomB
190
+ c.exitBtext = endText
191
+ end
192
+ c.type = style
193
+ c.dir = flow
194
+ debug c
195
+ rescue Section::ConnectionError
196
+ end
197
+ end
198
+
199
+ }
200
+
201
+ end
202
+
203
+
204
+
205
+ def reposition
206
+ @map.sections.each do |sect|
207
+ minXY, = sect.min_max_rooms
208
+ sect.rooms.each do |r|
209
+ r.x -= minXY[0]
210
+ r.y -= minXY[1]
211
+ r.x /= 128.0
212
+ r.y /= 64.0
213
+ end
214
+ end
215
+
216
+ @map.sections.each do |sect|
217
+ sect.rooms.each_with_index do |r, idx|
218
+ x = r.x
219
+ y = r.y
220
+ xf = x.floor
221
+ yf = y.floor
222
+ if x != xf or y != yf
223
+ sect.rooms.each do |r2|
224
+ next if r == r2
225
+ if xf == r2.x.floor and yf == r2.y.floor
226
+ dx = (x - xf).ceil
227
+ dy = (y - yf).ceil
228
+ sect.shift(x, y, dx, dy)
229
+ break
230
+ end
231
+ end
232
+ end
233
+ r.x = r.x.floor.to_i
234
+ r.y = r.y.floor.to_i
235
+ end
236
+ end
237
+ end
238
+
239
+ def initialize(file, map = Map.new('Trizbort Imported Map'))
240
+ @map = map
241
+
242
+ f = File.open( file )
243
+ @doc = REXML::Document.new f
244
+
245
+ parse
246
+
247
+ reposition
248
+
249
+ @map.fit
250
+ @map.section = 0
251
+
252
+ if @map.kind_of?(FXMap)
253
+ @map.filename = file.sub(/\.trizbort$/i, '.map')
254
+ @map.navigation = true
255
+ @map.window.show
256
+ end
257
+ end
258
+
259
+ end
@@ -0,0 +1,107 @@
1
+
2
+
3
+
4
+ class TrizbortWriter
5
+
6
+ W = 128
7
+ H = 64
8
+
9
+
10
+ DIRECTIONS = [
11
+ 'n',
12
+ 'ne',
13
+ 'e',
14
+ 'se',
15
+ 's',
16
+ 'sw',
17
+ 'w',
18
+ 'nw',
19
+ ]
20
+
21
+ OTHERDIRS = [
22
+ '',
23
+ 'u',
24
+ 'd',
25
+ 'in',
26
+ 'out',
27
+ ]
28
+
29
+ def write_objects( room )
30
+ if room.objects
31
+ @f.print "\t\t\ŧ<objects>"
32
+ room.objects.split("\n").each_with_index { |obj,idx|
33
+ if idx > 0
34
+ @f.print "|"
35
+ end
36
+ @f.print "#{obj}"
37
+ }
38
+ @f.puts "</objects>"
39
+ end
40
+ end
41
+
42
+ def write_map
43
+ @f.puts "\t<map>"
44
+ hash = {}
45
+ x = 0
46
+ y = 0
47
+ maxX = 0
48
+ maxY = 0
49
+ id = 0
50
+ @map.sections.each { |s|
51
+ s.rooms.each { |r|
52
+ @f.puts "\t\t<room id=\"#{id}\" name=\"#{r.name}\" x=\"#{x + r.x*(W+32)}\" y=\"#{y + r.y*(H+32)}\" w=\"#{W}\" h=\"#{H}\">"
53
+ write_objects r
54
+ @f.puts "\t\t</room>"
55
+ hash[r] = id
56
+ id += 1
57
+ maxX = r.x if r.x > maxX
58
+ maxY = r.y if r.y > maxY
59
+ }
60
+ x = maxX * (W+32)
61
+ s.connections.each { |c|
62
+ @f.print "\t\t<line id=\"#{id}\""
63
+ if c.type == Connection::SPECIAL
64
+ @f.print " style=\"dashed\""
65
+ end
66
+ if c.dir == Connection::AtoB
67
+ @f.print " flow=\"oneWay\""
68
+ end
69
+ @f.puts ">"
70
+ dirA, dirB = c.dirs
71
+ id += 1
72
+ @f.print "\t\t\t<dock index=\"0\" id=\"#{hash[c.roomA]}\" "
73
+ portA = DIRECTIONS[dirA]
74
+ @f.puts "port=\"#{portA}\" />"
75
+ if c.roomB
76
+ portB = DIRECTIONS[dirB]
77
+ @f.print "\t\t\t<dock index=\"1\" id=\"#{hash[c.roomB]}\" "
78
+ @f.puts "port=\"#{portB}\" />"
79
+ end
80
+ @f.puts "\t\t</line>"
81
+ }
82
+ }
83
+ @f.puts "\t</map>"
84
+ end
85
+
86
+ def write_info
87
+ @f.puts "\t<info>\n\t\t<title>#{@map.name}</title>"
88
+ @f.puts "\t\t<author>#{@map.creator}</author>"
89
+ @f.puts "\t</info>"
90
+ end
91
+
92
+ def write
93
+ @f.puts '<?xml version="1.0" encoding="utf-8"?>'
94
+ @f.puts '<trizbort>'
95
+ write_info
96
+ write_map
97
+ @f.puts '</trizbort>'
98
+ end
99
+
100
+ def initialize(map, fileroot)
101
+ @root = fileroot
102
+ @base = File.basename(@root)
103
+ @f = File.open "#{fileroot}.trizbort", 'w'
104
+ @map = map
105
+ write
106
+ end
107
+ end
@@ -55,6 +55,9 @@ MSG_SAVE_MAP = 'Save Map'
55
55
  MSG_WAS_MODIFIED = "was modified.\n"
56
56
  MSG_SHOULD_I_SAVE_CHANGES = 'Should I save the changes?'
57
57
 
58
+ MSG_SAVE_MAP_AS_TRIZBORT = 'Save Map as Trizbort File'
59
+ FMT_TRIZBORT = 'Trizbort Map (*.trizbort)'
60
+
58
61
  MSG_SAVE_MAP_AS_IFM = 'Save Map as IFM File'
59
62
  FMT_IFM = 'IFM Map (*.ifm)'
60
63
 
@@ -256,10 +259,11 @@ MENU_SAVE = "&Save\tCtl-S\tSave document."
256
259
  MENU_SAVE_AS = "Save &As...\t\tSave document to another file."
257
260
 
258
261
  MENU_EXPORT = 'Export'
259
- MENU_EXPORT_PDF = "&Export as PDF...\t\tExport map as Acrobat PDF document."
260
- MENU_EXPORT_IFM = "&Export as IFM...\t\tExport map as an IFM map."
261
- MENU_EXPORT_INFORM = "&Export as Inform Source...\t\tExport map as an Inform source code file."
262
- MENU_EXPORT_TADS = "&Export as TADS3 Source...\t\tExport map as a TADS3 source code file."
262
+ MENU_EXPORT_PDF = "Export as &PDF...\t\tExport map as Acrobat PDF document."
263
+ MENU_EXPORT_TRIZBORT = "Export as Triz&bort...\t\tExport map as a Trizbort map."
264
+ MENU_EXPORT_IFM = "Export as &IFM...\t\tExport map as an IFM map."
265
+ MENU_EXPORT_INFORM = "Export as &Inform Source...\t\tExport map as an Inform source code file."
266
+ MENU_EXPORT_TADS = "Export as &TADS3 Source...\t\tExport map as a TADS3 source code file."
263
267
 
264
268
  MENU_PRINT = 'Print'
265
269
  MENU_PRINT_MAP = "&Map...\t\tPrint map (as graph)."
@@ -59,6 +59,9 @@ MSG_SAVE_MAP = 'Grabar Mapa'
59
59
  MSG_WAS_MODIFIED = "fue modificado.\n"
60
60
  MSG_SHOULD_I_SAVE_CHANGES = '¿Grabo los cambios?'
61
61
 
62
+ MSG_SAVE_MAP_AS_TRIZBORT = 'Grabar Mapa como Archivo Trizbort'
63
+ FMT_TRIZBORT = 'Mapa Trizbort (*.trizbort)'
64
+
62
65
  MSG_SAVE_MAP_AS_IFM = 'Grabar Mapa como Archivo IFM'
63
66
  FMT_IFM = 'Mapa IFM (*.ifm)'
64
67
 
@@ -261,10 +264,11 @@ MENU_SAVE = "&Grabar\tCtl-G\tGrabar un mapa."
261
264
  MENU_SAVE_AS = "Grabar &Como...\t\tGrabar mapa en otro archivo."
262
265
 
263
266
  MENU_EXPORT = 'Exportar'
264
- MENU_EXPORT_PDF = "&Exportar como PDF...\t\tExportar mapa como documento Acrobat PDF."
265
- MENU_EXPORT_IFM = "&Exportar como IFM...\t\tExportar mapa como un archivo IFM."
266
- MENU_EXPORT_INFORM = "&Exportar como Código Fuente de Inform...\t\tExportar mapa como un código fuente de Inform."
267
- MENU_EXPORT_TADS = "&Exportar como Código Fuente de TADS3...\t\tExportar mapa como un código fuente de TADS3."
267
+ MENU_EXPORT_PDF = "Exportar como &PDF...\t\tExportar mapa como documento Acrobat PDF."
268
+ MENU_EXPORT_TRIZBORT = "Exportar como Triz&bort...\t\tExportar mapa como un archivo Trizbort."
269
+ MENU_EXPORT_IFM = "Exportar como &IFM...\t\tExportar mapa como un archivo IFM."
270
+ MENU_EXPORT_INFORM = "Exportar como Código Fuente de &Inform...\t\tExportar mapa como un código fuente de Inform."
271
+ MENU_EXPORT_TADS = "Exportar como Código Fuente de &TADS3...\t\tExportar mapa como un código fuente de TADS3."
268
272
 
269
273
  MENU_PRINT = 'Imprimir'
270
274
  MENU_PRINT_MAP = "&Mapa...\t\tImprimir mapa (como gráfico)."
Binary file
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ifmapper
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 0
10
- version: 1.1.0
9
+ - 1
10
+ version: 1.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Gonzalo Garramuno
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-23 00:00:00 -03:00
18
+ date: 2011-06-03 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -117,6 +117,8 @@ files:
117
117
  - lib/IFMapper/TADSWriter.rb
118
118
  - lib/IFMapper/TranscriptDialogBox.rb
119
119
  - lib/IFMapper/TranscriptReader.rb
120
+ - lib/IFMapper/TrizbortReader.rb
121
+ - lib/IFMapper/TrizbortWriter.rb
120
122
  - lib/IFMapper/FXPDFMapExporterOptionsDialogBox.rb
121
123
  - lib/IFMapper/FXRoom.rb
122
124
  - lib/IFMapper/FXRoomDialogBox.rb