ifmapper 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/HISTORY.txt +2 -0
  2. data/IFMapper.gemspec +21 -0
  3. data/IFMapper.rb +27 -0
  4. data/icons/copy.png +0 -0
  5. data/icons/cut.png +0 -0
  6. data/icons/filenew.png +0 -0
  7. data/icons/fileopen.png +0 -0
  8. data/icons/filesave.png +0 -0
  9. data/icons/filesaveas.png +0 -0
  10. data/icons/help.png +0 -0
  11. data/icons/kill.png +0 -0
  12. data/icons/nextpage.png +0 -0
  13. data/icons/paste.png +0 -0
  14. data/icons/prevpage.png +0 -0
  15. data/icons/printicon.png +0 -0
  16. data/icons/redo.png +0 -0
  17. data/icons/saveas.png +0 -0
  18. data/icons/undo.png +0 -0
  19. data/icons/winapp.png +0 -0
  20. data/icons/zoom.png +0 -0
  21. data/lib/IFMapper/Connection.rb +63 -0
  22. data/lib/IFMapper/FXAboutDialogBox.rb +32 -0
  23. data/lib/IFMapper/FXConnection.rb +283 -0
  24. data/lib/IFMapper/FXConnectionDialogBox.rb +126 -0
  25. data/lib/IFMapper/FXMap.rb +1614 -0
  26. data/lib/IFMapper/FXMapDialogBox.rb +51 -0
  27. data/lib/IFMapper/FXMapFileDialog.rb +29 -0
  28. data/lib/IFMapper/FXMapperSettings.rb +45 -0
  29. data/lib/IFMapper/FXMapperWindow.rb +1051 -0
  30. data/lib/IFMapper/FXPage.rb +24 -0
  31. data/lib/IFMapper/FXPageDialogBox.rb +38 -0
  32. data/lib/IFMapper/FXRoom.rb +218 -0
  33. data/lib/IFMapper/FXRoomDialogBox.rb +119 -0
  34. data/lib/IFMapper/FXSearchDialogBox.rb +51 -0
  35. data/lib/IFMapper/FXSpline.rb +54 -0
  36. data/lib/IFMapper/FXWarningBox.rb +45 -0
  37. data/lib/IFMapper/IFMReader.rb +613 -0
  38. data/lib/IFMapper/Map.rb +110 -0
  39. data/lib/IFMapper/PDFMapExporter.rb +315 -0
  40. data/lib/IFMapper/Page.rb +158 -0
  41. data/lib/IFMapper/Room.rb +104 -0
  42. data/maps/Bureaucracy.ifm +75 -0
  43. data/maps/Hollywood_Hijinx.ifm +149 -0
  44. data/maps/Jigsaw.ifm +806 -0
  45. data/maps/LGOP.ifm +705 -0
  46. data/maps/Mercy.ifm +76 -0
  47. data/maps/Planetfall.ifm +186 -0
  48. data/maps/Plundered_Hearts.ifm +251 -0
  49. data/maps/Ralph.ifm +50 -0
  50. data/maps/Robots_of_Dawn.ifm +224 -0
  51. data/maps/Seastalker.ifm +149 -0
  52. data/maps/Sherlock.ifm +209 -0
  53. data/maps/SoFar.ifm +72 -0
  54. data/maps/Starcross.ifm +170 -0
  55. data/maps/Suspended.ifm +82 -0
  56. data/maps/Wishbringer.ifm +277 -0
  57. data/maps/Wishbringer2.ifm +246 -0
  58. data/maps/Zork1.ifm +410 -0
  59. data/maps/Zork2.ifm +150 -0
  60. data/maps/Zork3.ifm +136 -0
  61. data/maps/Zork_Zero.ifm +557 -0
  62. data/maps/anchor.ifm +645 -0
  63. data/maps/atrox.ifm +134 -0
  64. data/maps/awaken.ifm +116 -0
  65. data/maps/babel.ifm +279 -0
  66. data/maps/bse.ifm +150 -0
  67. data/maps/change.ifm +128 -0
  68. data/maps/curses.ifm +307 -0
  69. data/maps/curves.ifm +529 -0
  70. data/maps/edifice.ifm +158 -0
  71. data/maps/frozen.ifm +126 -0
  72. data/maps/glow.ifm +101 -0
  73. data/maps/library.ifm +93 -0
  74. data/maps/mindelec.ifm +89 -0
  75. data/maps/minster.ifm +234 -0
  76. data/maps/muse.ifm +154 -0
  77. data/maps/paperchase.ifm +110 -0
  78. data/maps/space_st.ifm +104 -0
  79. data/maps/stationfall.ifm +320 -0
  80. data/maps/theatre.ifm +182 -0
  81. data/maps/toonesia.ifm +54 -0
  82. data/maps/tortoise.ifm +72 -0
  83. data/maps/vgame.ifm +219 -0
  84. data/maps/weather.ifm +98 -0
  85. data/maps/windhall.ifm +154 -0
  86. data/maps/zebulon.ifm +68 -0
  87. metadata +144 -0
@@ -0,0 +1,24 @@
1
+
2
+ require 'IFMapper/FXConnection'
3
+ require 'IFMapper/FXRoom'
4
+ require 'IFMapper/Page'
5
+
6
+ class FXPage < Page
7
+ def new_connection( roomA, exitA, roomB, exitB = nil )
8
+ c = FXConnection.new( roomA, roomB )
9
+ return _new_connection(c, roomA, exitA, roomB, exitB)
10
+ end
11
+
12
+ def new_room(x, y)
13
+ r = FXRoom.new( x, y, 'New Location' )
14
+ return _new_room(r, x, y)
15
+ end
16
+
17
+ def properties(map)
18
+ if not @win
19
+ @win = FXPageDialogBox.new(map)
20
+ end
21
+ @win.copy_from(self)
22
+ @win.show
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+
2
+
3
+ class FXPageDialogBox < FXDialogBox
4
+
5
+ def copy_to()
6
+ @page.name = @name.text
7
+ @map.update_title
8
+ end
9
+
10
+ def copy_from(page)
11
+ @name.text = page.name.to_s
12
+ @page = page
13
+ end
14
+
15
+ def initialize(map)
16
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
17
+
18
+ super( map.window, "Page Information", decor, 40, 40, 0, 0 )
19
+ mainFrame = FXVerticalFrame.new(self,
20
+ FRAME_SUNKEN|FRAME_THICK|
21
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
22
+
23
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
24
+
25
+ FXLabel.new(frame, "Name: ", nil, 0, LAYOUT_FILL_X)
26
+ @name = FXTextField.new(frame, 40, nil, 0, LAYOUT_FILL_ROW)
27
+
28
+ frame = FXVerticalFrame.new(mainFrame,
29
+ LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
30
+
31
+
32
+ @name.connect(SEL_CHANGED) { copy_to() }
33
+ @map = map
34
+
35
+ # We need to create the dialog box first, so we can use select text.
36
+ create
37
+ end
38
+ end
@@ -0,0 +1,218 @@
1
+
2
+ require 'IFMapper/Room'
3
+ require 'IFMapper/FXRoomDialogBox'
4
+
5
+ #
6
+ # Class used to reprent an IF room
7
+ #
8
+ class FXRoom < Room
9
+ attr_accessor :x, :y, :xx, :yy
10
+ attr_accessor :selected
11
+
12
+ @@win = nil
13
+
14
+ def initialize(x, y, *opts)
15
+ @xx = x * WW + WS_2
16
+ @yy = y * HH + HS_2
17
+ @selected = false
18
+ super(x, y, *opts)
19
+ end
20
+
21
+ def x=(v)
22
+ @x = v
23
+ @xx = v * WW + WS_2
24
+ end
25
+
26
+ def y=(v)
27
+ @y = v
28
+ @yy = v * HH + HS_2
29
+ end
30
+
31
+ def copy(b)
32
+ @name = b.name
33
+ @objects = b.objects
34
+ @tasks = b.tasks
35
+ @darkness = b.darkness
36
+ end
37
+
38
+ def selected=(value)
39
+ if value and @@win
40
+ @@win.copy_from(self)
41
+ end
42
+ @selected = value
43
+ end
44
+
45
+ def modal_properties(map)
46
+ shown = @@win and @@win.shown?
47
+ if shown
48
+ @@win.hide
49
+ end
50
+ win = FXRoomDialogBox.new(map, self, nil, true)
51
+ # win.setFocus
52
+ win.setFocus
53
+ win.show
54
+ win.copy_from(self)
55
+ if win.execute != 0
56
+ win.copy_to()
57
+ else
58
+ return false
59
+ end
60
+ if shown
61
+ @@win.show
62
+ end
63
+ return true
64
+ end
65
+
66
+ # Open a new requester to change room properties
67
+ def properties( map, event = nil )
68
+ if not @@win
69
+ @@win = FXRoomDialogBox.new(map, self, event, false)
70
+ else
71
+ @@win.map = map
72
+ end
73
+ @@win.setFocus
74
+ @@win.show
75
+ @@win.copy_from(self)
76
+ return
77
+ end
78
+
79
+ #
80
+ # Given a connection and/or an exit index, return the x and y offset
81
+ # multipliers needed from the top corner of the box.
82
+ #
83
+ def _corner(c, idx)
84
+ idx = @exits.index(c) unless idx
85
+ raise "corner: #{c} not found in #{self}" unless idx
86
+ x = y = 0
87
+ case idx
88
+ when 0
89
+ x = 0.5
90
+ when 1
91
+ x = 1
92
+ when 2
93
+ x = 1
94
+ y = 0.5
95
+ when 3
96
+ x = 1
97
+ y = 1
98
+ when 4
99
+ x = 0.5
100
+ y = 1
101
+ when 5
102
+ y = 1
103
+ when 6
104
+ y = 0.5
105
+ when 7
106
+ else
107
+ raise "error wrong index #{idx}"
108
+ end
109
+ return [ x, y ]
110
+ end
111
+
112
+
113
+ # Given a connection belonging to a room, return draw coordinate
114
+ # of that corner.
115
+ def corner( c, zoom, idx = nil )
116
+ x, y = _corner(c, idx)
117
+ x = @xx + W * x
118
+ y = @yy + H * y
119
+ return [x * zoom, y * zoom]
120
+ end
121
+
122
+
123
+ def draw_index(dc, zoom, idx)
124
+ x = (@xx + W - 20 ) * zoom
125
+ y = (@yy + HH - HS - 5 ) * zoom
126
+ dc.drawText(x, y, (idx + 1).to_s)
127
+ end
128
+
129
+
130
+ def draw_box(dc, zoom, idx, opt)
131
+ if @selected
132
+ dc.foreground = 'yellow'
133
+ else
134
+ if @darkness
135
+ dc.foreground = opt['Box Darkness Color']
136
+ else
137
+ dc.foreground = opt['Box BG Color']
138
+ end
139
+ end
140
+
141
+ x = @xx * zoom
142
+ y = @yy * zoom
143
+ w = W * zoom
144
+ h = H * zoom
145
+ dc.fillRectangle(x, y, w, h)
146
+
147
+
148
+ dc.foreground = opt['Box Border Color']
149
+ dc.lineWidth = 2 * zoom
150
+ dc.lineWidth = 2 if dc.lineWidth < 2
151
+ dc.lineStyle = LINE_SOLID
152
+ dc.drawRectangle(x, y, w, h)
153
+
154
+ # Draw grey square for index
155
+ if opt['Location Numbers']
156
+ dc.foreground = opt['Box Number Color']
157
+ x += w # Index goes at bottom right of square
158
+ y += h
159
+ w = WIDX * zoom
160
+ h = HIDX * zoom
161
+ x -= w
162
+ y -= h
163
+ dc.fillRectangle(x, y, w, h)
164
+
165
+ dc.foreground = opt['Box Border Color']
166
+ dc.drawRectangle(x, y, w, h)
167
+
168
+ draw_index(dc, zoom, idx)
169
+ end
170
+ end
171
+
172
+ def draw_text_wrap(dc, x, y, zoom, maxLen, text)
173
+ if text.size > maxLen
174
+ str = text
175
+ fh = dc.font.getFontHeight
176
+ while str and str.size > maxLen
177
+ idx = str.rindex(/[ -]/, maxLen)
178
+ unless idx
179
+ idx = str.index(/[ -]/, maxLen)
180
+ idx = str.size unless idx
181
+ end
182
+ dc.drawText(x, y, str[0..idx])
183
+ str = str[idx+1..-1]
184
+ y += fh
185
+ str = nil if y > (@yy + H) * zoom
186
+ end
187
+ dc.drawText(x, y, str) if str
188
+ else
189
+ dc.drawText(x, y, text)
190
+ end
191
+ return [x, y]
192
+ end
193
+
194
+ def draw_name(dc, zoom)
195
+ x = (@xx + 5) * zoom
196
+ y = (@yy + 15) * zoom
197
+ return draw_text_wrap( dc, x, y, zoom, 15, @name )
198
+ end
199
+
200
+ def draw_objects(dc, zoom, x, y)
201
+ return if @objects == ''
202
+ fh = dc.font.getFontHeight
203
+ y += fh
204
+ objs = @objects.split("\n")
205
+ objs = objs.join(', ')
206
+ return draw_text_wrap( dc, x, y, zoom, 23, objs )
207
+ end
208
+
209
+
210
+ def draw(dc, zoom, idx, opt, data)
211
+ draw_box(dc, zoom, idx, opt)
212
+ dc.font = data['font']
213
+ x, y = draw_name(dc, zoom)
214
+ dc.font = data['objfont']
215
+ draw_objects(dc, zoom, x, y)
216
+ end
217
+
218
+ end
@@ -0,0 +1,119 @@
1
+
2
+
3
+ #
4
+ # Class used to display a room dialog box
5
+ #
6
+ class FXRoomDialogBox < FXDialogBox
7
+
8
+ attr_writer :map
9
+
10
+ def copy_to()
11
+ @room.name = @name.text
12
+ @room.objects = @objects.text
13
+ @room.objects.gsub!(/[\.,\t]+/, "\n")
14
+ @room.tasks = @tasks.text
15
+ @room.darkness = (@darkness.checkState == 1)
16
+
17
+ ## we should do something like:
18
+ ## @room.draw(dc)
19
+ ## for faster updates
20
+ @map.draw
21
+ end
22
+
23
+
24
+ def copy_from(room)
25
+ @name.text = room.name
26
+ @darkness.checkState = room.darkness
27
+ @objects.text = room.objects
28
+ @tasks.text = room.tasks
29
+ # Select text for quick editing if it uses default location name
30
+ @name.setCursorPos room.name.size # - 1 if room.name.size > 0
31
+ if room.name == 'New Location'
32
+ @name.selectAll
33
+ end
34
+ if self.shown?
35
+ @name.setFocus
36
+ end
37
+ @room = room
38
+ if @map.navigation
39
+ @name.disable
40
+ @darkness.disable
41
+ @objects.disable
42
+ @tasks.disable
43
+ else
44
+ @name.enable
45
+ @darkness.enable
46
+ @objects.enable
47
+ @tasks.enable
48
+ end
49
+ end
50
+
51
+ def initialize(map, room, event = nil, modal = nil)
52
+ pos = [40, 40]
53
+ if event
54
+ pos = [ event.last_x, event.last_y ]
55
+ end
56
+ maxW = map.window.width - 390
57
+ maxH = map.window.height - 300
58
+ pos[0] = maxW if pos[0] > maxW
59
+ pos[1] = maxH if pos[1] > maxH
60
+
61
+ if modal
62
+ decor = DECOR_TITLE|DECOR_BORDER
63
+ else
64
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
65
+ end
66
+
67
+ super( map.window, "Room Information", decor, pos[0], pos[1], 0, 0 )
68
+ mainFrame = FXVerticalFrame.new(self,
69
+ FRAME_SUNKEN|FRAME_THICK|
70
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
71
+
72
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
73
+
74
+ FXLabel.new(frame, "Location: ", nil, 0, LAYOUT_FILL_X)
75
+ @name = FXTextField.new(frame, 40, nil, 0, LAYOUT_FILL_ROW)
76
+
77
+ frame = FXVerticalFrame.new(mainFrame,
78
+ LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
79
+
80
+
81
+ frame2 = FXHorizontalFrame.new(frame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
82
+ FXLabel.new(frame2, "Objects: ", nil, 0, LAYOUT_FILL_X)
83
+ @darkness = FXCheckButton.new(frame2, "Darkness", nil, 0,
84
+ ICON_BEFORE_TEXT|LAYOUT_CENTER_X|
85
+ LAYOUT_SIDE_RIGHT)
86
+
87
+ @objects = FXText.new(frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
88
+ @objects.visibleRows = 8
89
+
90
+ frame = FXVerticalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|
91
+ LAYOUT_FILL_Y)
92
+ FXLabel.new(frame, "Tasks: ", nil, 0, LAYOUT_FILL_X)
93
+ @tasks = FXText.new(frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
94
+ @tasks.visibleRows = 8
95
+
96
+ if modal
97
+ buttons = FXHorizontalFrame.new(mainFrame,
98
+ LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|
99
+ PACK_UNIFORM_WIDTH)
100
+ # Accept
101
+ @ok = FXButton.new(buttons, "&Accept", nil, self, FXDialogBox::ID_ACCEPT,
102
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
103
+
104
+ # Cancel
105
+ cmd = FXButton.new(buttons, "&Cancel", nil, self, FXDialogBox::ID_CANCEL,
106
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
107
+ else
108
+ @name.connect(SEL_CHANGED) { copy_to() }
109
+ @objects.connect(SEL_CHANGED) { copy_to()}
110
+ @tasks.connect(SEL_CHANGED) { copy_to() }
111
+ @darkness.connect(SEL_COMMAND) { copy_to() }
112
+ end
113
+
114
+ @map = map
115
+
116
+ # We need to create the dialog box first, so we can use select text.
117
+ create
118
+ end
119
+ end
@@ -0,0 +1,51 @@
1
+
2
+ #
3
+ # Class used to display a connection dialog box
4
+ #
5
+ class FXSearchDialogBox < FXDialogBox
6
+ attr_accessor :index
7
+
8
+ def text=(x)
9
+ @search.text = x
10
+ @index = 0
11
+ end
12
+
13
+ def text
14
+ return @search.text
15
+ end
16
+
17
+ def proc=(p)
18
+ @search.connect(SEL_CHANGED, p)
19
+ @proc = p
20
+ end
21
+
22
+ def initialize(parent)
23
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
24
+ super( parent, '', decor, 40, 200, 0, 0 )
25
+ @index = 0
26
+ mainFrame = FXVerticalFrame.new(self,
27
+ FRAME_SUNKEN|FRAME_THICK|
28
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
29
+
30
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
31
+
32
+ FXLabel.new(frame, "Search String: ", nil, 0, LAYOUT_FILL_X)
33
+ @search = FXTextField.new(frame, 40, nil, 0, LAYOUT_FILL_ROW)
34
+
35
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
36
+ @previous = FXButton.new(frame, "Previous Match")
37
+ @previous.connect(SEL_COMMAND) { |sender, sel, e |
38
+ @index -= 1 if @index > 0
39
+ sender.handle(self, MKUINT(message, SEL_CHANGED), nil)
40
+ @proc.call @search, nil, nil if @proc
41
+ }
42
+ @next = FXButton.new(frame, "Next Match")
43
+ @next.connect(SEL_COMMAND) { |sender, sel, e |
44
+ @index += 1
45
+ @proc.call @search, nil, nil if @proc
46
+ }
47
+
48
+ # We need to create the dialog box first, so we can use select text.
49
+ create
50
+ end
51
+ end