Class: FXMap
- Defined in:
- lib/IFMapper/TrizbortReader.rb,
lib/IFMapper/FXMap.rb,
lib/IFMapper/GUEReader.rb,
lib/IFMapper/IFMReader.rb,
lib/IFMapper/MapReader.rb,
lib/IFMapper/SVGMapExporter.rb,
lib/IFMapper/PDFMapExporter_prawn.rb,
lib/IFMapper/PDFMapExporter_pdfwriter.rb
Overview
Trizbort map reader
Constant Summary collapse
- FILE_FORMAT_VERSION =
1
- @@win =
Map Info window
nil
- @@roomlist =
Room List Window
nil
- @@itemlist =
Item List Window
nil
- @@tooltip =
Cursors
nil
- @@cursor_arrow =
nil
- @@cursor_cross =
nil
- @@cursor_n =
nil
- @@cursor_ne =
nil
- @@cursor_e =
nil
- @@cursor_se =
nil
- @@cursor_s =
nil
- @@cursor_sw =
nil
- @@cursor_w =
nil
- @@cursor_nw =
nil
Instance Attribute Summary collapse
-
#automap ⇒ Object
readonly
Mutex to avoid racing conditions while automapping.
-
#complexConnection ⇒ Object
readonly
Complex connection in progress.
-
#filename ⇒ Object
Filename of current map (if any).
-
#modified ⇒ Object
Was map modified since being loaded?.
-
#mouseButton ⇒ Object
readonly
Mouse button pressed.
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
-
#navigation ⇒ Object
Returns the value of attribute navigation.
-
#options ⇒ Object
Map is navigation mode (no new nodes can be created).
-
#pdflocationnos ⇒ Object
boolean value indicating whether the user wants to see location nos.
-
#pdfpapersize ⇒ Object
Returns the value of attribute pdfpapersize.
-
#pmap ⇒ Object
readonly
pmap is a path map (a matrix or grid used for path finding).
-
#version ⇒ Object
readonly
file format version.
-
#window ⇒ Object
readonly
Fox Window for this map.
-
#zoom ⇒ Object
Upgrade this if incompatible changes are made in the class so that file loading of old files can still be checked against.
Attributes inherited from Map
#creator, #date, #height, #name, #section, #sections, #width
Class Method Summary collapse
Instance Method Summary collapse
-
#_changed ⇒ Object
Map has changed dramatically.
-
#_cut_selected ⇒ Object
Handle ‘cutting’ any selected rooms and/or connections.
-
#_free_area?(x, y, w, h) ⇒ Boolean
Determine whether a pathmap area from x,y to x+w,y+h is free of rooms.
-
#_make_cursors ⇒ Object
Create cursors.
-
#_make_widgets ⇒ Object
Create widgets for this map window.
- #_new_complex_connection(roomA, exitA) ⇒ Object
-
#_save ⇒ Object
Perform the actual saving of the map.
-
#add_path_pt(c, x, y) ⇒ Object
Add a new path point to a connection.
- #cannot_automap(why) ⇒ Object
-
#center_view_on_room(r) ⇒ Object
Given a room, center scrollwindow so room is visible.
-
#center_view_on_xy(xx, yy) ⇒ Object
Given an x and y coordinate for the canvas, center on it.
-
#clean_exits(room) ⇒ Object
Clean all paths from path map for a room.
-
#clean_path(c) ⇒ Object
Given a connection, clean its path from path map.
-
#clean_room_selection(selection) ⇒ Object
Given a selection of rooms, clear all of them from path map.
-
#clear_selection ⇒ Object
Clear rooms/connections selected.
-
#click_type(x, y) ⇒ Object
Given a canvas (mouse) x/y position, return:.
-
#close_cb ⇒ Object
Close the map.
-
#complex_connection ⇒ Object
Start a complex connection.
-
#copy(b) ⇒ Object
Used to copy relevant data from one (temporary) map to another.
-
#create_pathmap ⇒ Object
Recreate the pathmap based on rooms and connections This routine is used on loading a new map.
-
#current_room ⇒ Object
Return the current active room.
-
#cursor_switch(x, y) ⇒ Object
Based on x,y coordinate, switch mouse icon shape.
- #cut_selected ⇒ Object
-
#delete_room(r) ⇒ Object
Given a room, delete it.
-
#delete_room_only(r) ⇒ Object
Given a room, delete it.
-
#delete_section ⇒ Object
Delete current section from map.
-
#delete_selected ⇒ Object
Handle deleting selected rooms and/or connections.
-
#double_click_cb(selection, event) ⇒ Object
Handle mouse button double clicks in canvas.
-
#draw(sender = nil, sel = nil, event = nil) ⇒ Object
Draw map.
-
#draw_background(dc, event = nil) ⇒ Object
Clean background to solid color.
-
#draw_connections(dc) ⇒ Object
Draw connections among rooms.
-
#draw_diagonal_connections(dc, event) ⇒ Object
Draw template of diagonal connections in grid background.
-
#draw_grid(dc, event = nil) ⇒ Object
Draw template of room squares in background.
-
#draw_mapname(dc) ⇒ Object
Draw mapname.
-
#draw_room(room) ⇒ Object
Draw a single room (callback used when editing room dialog box).
-
#draw_rooms(dc) ⇒ Object
Draw all rooms in current section.
-
#draw_straight_connections(dc, event) ⇒ Object
Draw template of straight connections in grid background.
-
#dump_pathmap ⇒ Object
A simple debugging function that will spit out the path map with a very simple ascii representation.
-
#empty_pathmap ⇒ Object
Reinitialize the pathmap to an empty matrix.
-
#export_ifm(file) ⇒ Object
Export map as an IFM map file.
-
#export_inform(file, version = 6) ⇒ Object
Export map as a set of Inform source code files.
-
#export_inform7(file) ⇒ Object
Export map as a set of Inform source code files.
-
#export_tads(file) ⇒ Object
Export map as a set of TADS3 source code files.
-
#export_trizbort(file) ⇒ Object
Export map as a set of Inform source code files.
-
#find_empty_area(rooms) ⇒ Object
Given a list of rooms, find an area in the map where we could place them.
-
#free?(x, y) ⇒ Boolean
Return true or false if map is free at location x, y.
-
#get_quadrant(ax, ay) ⇒ Object
Given a mouse x/y position to WS/HS, return an index indicating what quadrant it belongs to.
-
#get_selection ⇒ Object
Return current selection as an array of rooms and an array of connections.
-
#help_cb(sender, sel, event) ⇒ Object
Show some help status in status line based on cursor position.
-
#initialize(name, parent = nil, default_options = nil, icon = nil, menu = nil, mode = nil, x = 0, y = 0, w = 0, h = 0) ⇒ FXMap
constructor
Main constructor.
-
#keypress_cb(server, sel, event) ⇒ Object
Handle a keypress.
-
#lmb_click_cb(sender, sel, event) ⇒ Object
Handle left mouse button click.
-
#marshal_dump ⇒ Object
Used for saving class with Marshal.
-
#marshal_load(variables) ⇒ Object
Used for loading class with Marshal.
- #max_width(opts) ⇒ Object
-
#mmb_click_cb(server, sel, event) ⇒ Object
Handle middle mouse button click in canvas.
-
#mmb_release_cb(server, sel, event) ⇒ Object
Handle release of middle mouse button.
-
#motion_cb(server, sel, event) ⇒ Object
Handle mouse motion in canvas.
-
#mousewheel_cb(sender, sel, event) ⇒ Object
zoom in/out based on mousewheel, keeping position relative to cursor position.
-
#move_thru(idx) ⇒ Object
Move through an exit into another room.
-
#move_to(idx) ⇒ Object
Move selected rooms in one of the 8 cardinal directions.
-
#navigation_warning ⇒ Object
Give user some warning if he tries to modify a read-only mode.
-
#new_complex_connection(x, y) ⇒ Object
Add a new complex connection (or its first point).
-
#new_room(x, y) ⇒ Object
Create a new room for the current section.
-
#new_section ⇒ Object
Add a new section to map and make it current.
-
#new_xy_connection(x, y) ⇒ Object
Add a new room connection among contiguous rooms.
-
#new_xy_room(x, y) ⇒ Object
Function used to add a new room.
-
#next_section ⇒ Object
Go to next section (if any).
- #num_sections ⇒ Object
-
#path_find(c) ⇒ Object
Given a connection, create the path for it, if not a simple connection.
- #pdf_draw_mapname(pdf, opts) ⇒ Object
- #pdf_draw_sections(pdf, opts) ⇒ Object
- #pdf_export(pdffile = Dir::tmpdir + "/ifmap.pdf", printer = nil) ⇒ Object
-
#previous_section ⇒ Object
Go to previous section (if any).
-
#print(printer) ⇒ Object
Print map.
-
#properties ⇒ Object
Open the map’s property window.
-
#quadrant_to_rooms(q, x, y) ⇒ Object
Given an x,y absolute position corresponding to a connection, return connected rooms (if any).
-
#remove_connection(c) ⇒ Object
Remove a connection from map, since path creation failed.
-
#rename_section ⇒ Object
Popup the section properties to allow renaming it.
-
#rmb_click_cb(sender, sel, event) ⇒ Object
Handle right mouse button click.
-
#rmb_link_menu(submenu, c, room, idx, old_idx) ⇒ Object
Add a proper link submenu option for an exit.
-
#save ⇒ Object
Save the map.
-
#save_as ⇒ Object
Save the map under a new filename, bringing up a file requester.
-
#section=(x) ⇒ Object
Jump to a certain section #.
-
#select_all ⇒ Object
Select all connections and rooms.
-
#select_rectangle(x1, y1, x2, y2) ⇒ Object
Select all rooms and connections within (drag) rectangle.
- #show_itemlist ⇒ Object
- #show_roomlist ⇒ Object
- #start_automap ⇒ Object
-
#status(msg) ⇒ Object
Spit out a new message to the status line.
- #stop_automap ⇒ Object
-
#store_room_selection(selection) ⇒ Object
Given a selection of rooms, clear all of them from path map.
- #svg_draw_current_section(opts, svgfile) ⇒ Object
- #svg_draw_section_separate(opts, idx, svgfile) ⇒ Object
- #svg_draw_sections(opts, svgfile) ⇒ Object
- #svg_draw_sections_separate(opts, svgfile) ⇒ Object
- #svg_export(svgfile, printer = nil) ⇒ Object
-
#to_object(x, y) ⇒ Object
Given a mouse click x/y position, return object(s) if any or nil.
-
#to_room(x, y) ⇒ Object
Given an x and y canvas position, return room object, complex connection or nil.
-
#tooltip_cb(sender, id, ptr) ⇒ Object
Based on mouse position on canvas, create a tooltip.
- #total_height(opts) ⇒ Object
-
#update_exits(selection) ⇒ Object
Find and update all paths in path map for a room.
- #update_itemlist ⇒ Object
-
#update_roomlist ⇒ Object
If roomlist window is present, update it.
-
#update_title ⇒ Object
Update the map window’s title.
-
#zoom_in ⇒ Object
Self-explanatory.
-
#zoom_out ⇒ Object
Self-explanatory.
Methods inherited from Map
#_check_section, #delete_connection, #delete_connection_at, #delete_room_at, #delete_section_at, #fit, #new_connection, #pack_sections, #shift, #verify_integrity
Constructor Details
#initialize(name, parent = nil, default_options = nil, icon = nil, menu = nil, mode = nil, x = 0, y = 0, w = 0, h = 0) ⇒ FXMap
Main constructor. Create the object, initialize the pathmap and initialize the widgets and cursors if a parent window is passed.
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 |
# File 'lib/IFMapper/FXMap.rb', line 1398 def initialize(name, parent = nil, = nil, icon = nil, = nil, mode = nil, x = 0, y = 0, w = 0, h = 0) @mutex = Mutex.new @automap = nil = false @modified = false @mouseButton = false @filename = nil @complexConnection = false super(name) if parent @window = FXMDIChild.new(parent, name, icon, , mode, x, y, w, h) = _make_cursors if not @@cursor_arrow end empty_pathmap self.zoom = 0.8 end |
Instance Attribute Details
#automap ⇒ Object (readonly)
Mutex to avoid racing conditions while automapping
28 29 30 |
# File 'lib/IFMapper/FXMap.rb', line 28 def automap @automap end |
#complexConnection ⇒ Object (readonly)
Complex connection in progress
30 31 32 |
# File 'lib/IFMapper/FXMap.rb', line 30 def complexConnection @complexConnection end |
#filename ⇒ Object
Filename of current map (if any)
19 20 21 |
# File 'lib/IFMapper/FXMap.rb', line 19 def filename @filename end |
#modified ⇒ Object
Was map modified since being loaded?
20 21 22 |
# File 'lib/IFMapper/FXMap.rb', line 20 def modified @modified end |
#mouseButton ⇒ Object (readonly)
Mouse button pressed
31 32 33 |
# File 'lib/IFMapper/FXMap.rb', line 31 def mouseButton @mouseButton end |
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
26 27 28 |
# File 'lib/IFMapper/FXMap.rb', line 26 def mutex @mutex end |
#navigation ⇒ Object
Returns the value of attribute navigation.
21 22 23 |
# File 'lib/IFMapper/FXMap.rb', line 21 def end |
#options ⇒ Object
Map is navigation mode (no new nodes can be created)
23 24 25 |
# File 'lib/IFMapper/FXMap.rb', line 23 def end |
#pdflocationnos ⇒ Object
boolean value indicating whether the user wants to see location nos
451 452 453 |
# File 'lib/IFMapper/PDFMapExporter_prawn.rb', line 451 def pdflocationnos @pdflocationnos end |
#pdfpapersize ⇒ Object
Returns the value of attribute pdfpapersize.
449 450 451 |
# File 'lib/IFMapper/PDFMapExporter_prawn.rb', line 449 def pdfpapersize @pdfpapersize end |
#pmap ⇒ Object (readonly)
pmap is a path map (a matrix or grid used for path finding).
Rooms and paths are recorded there. Path finding is needed to draw complex connections (ie. those that are farther than one square) We now also use this for selecting of stuff, particularly complex paths.
38 39 40 |
# File 'lib/IFMapper/FXMap.rb', line 38 def pmap @pmap end |
#version ⇒ Object (readonly)
file format version
25 26 27 |
# File 'lib/IFMapper/FXMap.rb', line 25 def version @version end |
#window ⇒ Object (readonly)
Fox Window for this map
24 25 26 |
# File 'lib/IFMapper/FXMap.rb', line 24 def window @window end |
#zoom ⇒ Object
Upgrade this if incompatible changes are made in the class so that file loading of old files can still be checked against.
18 19 20 |
# File 'lib/IFMapper/FXMap.rb', line 18 def zoom @zoom end |
Class Method Details
.no_maps ⇒ Object
1572 1573 1574 1575 1576 1577 1578 |
# File 'lib/IFMapper/FXMap.rb', line 1572 def self.no_maps @@roomlist.hide if @@roomlist @@itemlist.hide if @@itemlist @@win.hide if @@win FXRoom::no_maps FXConnection::no_maps end |
Instance Method Details
#_changed ⇒ Object
Map has changed dramatically. Update pathmap, title and redraw
60 61 62 63 64 65 66 |
# File 'lib/IFMapper/FXMap.rb', line 60 def _changed create_pathmap if @window and @window.shown? update_title draw end end |
#_cut_selected ⇒ Object
Handle ‘cutting’ any selected rooms and/or connections
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 |
# File 'lib/IFMapper/FXMap.rb', line 1422 def _cut_selected rooms, conns = get_selection ############################ # First, handle rooms... ############################ # Remove rooms from path map rooms.each { |r| @pmap[r.x][r.y] = nil } # Remove rooms from current section in map @sections[@section].rooms -= rooms # Add any connections pointing to removed rooms as # connection to remove rooms.each { |r| conns += r.exits.find_all { |e| e != nil } } ######################### # Now, handle connections ######################### conns.uniq! # Remove connections from path map conns.each { |c| clean_path(c) } # Remove connections from current section in map @sections[@section].connections -= conns return rooms, conns end |
#_free_area?(x, y, w, h) ⇒ Boolean
Determine whether a pathmap area from x,y to x+w,y+h is free of rooms
172 173 174 175 176 177 178 179 |
# File 'lib/IFMapper/FXMap.rb', line 172 def _free_area?(x, y, w, h) x.upto(x+w) { |xx| y.upto(y+h) { |yy| return false if @pmap.at(xx).at(yy).kind_of?(Room) } } return true end |
#_make_cursors ⇒ Object
Create cursors
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 |
# File 'lib/IFMapper/FXMap.rb', line 1323 def _make_cursors pix = [] 32.times { 32.times { pix << 255 << 255 << 255 << 255 } } pix = pix.pack('c*') ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each { |d| eval(" @@cursor_\#{d} = FXGIFCursor.new(@window.getApp, pix)\n FXFileStream.open('icons/room_\#{d}.gif', FXStreamLoad) { |stream|\n @@cursor_\#{d}.loadPixels(stream)\n }\n @@cursor_\#{d}.create\n EOF\n }\n\n @@cursor_move = FXCursor.new(@window.getApp, CURSOR_MOVE)\n @@cursor_move.create\n\n @@cursor_arrow = FXCursor.new(@window.getApp, CURSOR_ARROW)\n @@cursor_arrow.create\n \n @@cursor_cross = FXCursor.new(@window.getApp, CURSOR_CROSS)\n @@cursor_cross.create\nend\n") |
#_make_widgets ⇒ Object
Create widgets for this map window
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 |
# File 'lib/IFMapper/FXMap.rb', line 1352 def @scrollwindow = FXScrollWindow.new(@window, SCROLLERS_NORMAL|SCROLLERS_TRACK) width = WW * @width height = HH * @height @canvasFrame = FXVerticalFrame.new(@scrollwindow, FRAME_SUNKEN|LAYOUT_FILL_X| LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT) # First, create an off-screen image for drawing and double buffering @image = FXBMPImage.new(@window.getApp, nil, IMAGE_SHMI|IMAGE_SHMP, width, height) @image.create # Then create canvas @canvas = FXCanvas.new(@canvasFrame, nil, 0, LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT| LAYOUT_TOP|LAYOUT_LEFT, 0, 0, width, height) @dirty = true # @canvas.connect(SEL_UPDATE, method(:update_cb)) @canvas.connect(SEL_PAINT, method(:draw)) @canvas.backColor = ['BG Color'] @canvas.connect(SEL_MOUSEWHEEL, method(:mousewheel_cb)) @canvas.connect(SEL_LEFTBUTTONPRESS, method(:lmb_click_cb)) @canvas.connect(SEL_LEFTBUTTONRELEASE, method(:mmb_release_cb)) @canvas.connect(SEL_MOTION, method(:motion_cb)) @canvas.connect(SEL_MIDDLEBUTTONPRESS, method(:mmb_click_cb)) @canvas.connect(SEL_MIDDLEBUTTONRELEASE, method(:mmb_release_cb)) @canvas.connect(SEL_RIGHTBUTTONPRESS, method(:rmb_click_cb)) @canvas.connect(SEL_KEYPRESS, method(:keypress_cb)) if fxversion !~ /^1.2/ @@tooltip = FXToolTip.new(@canvas.app, FXToolTip::TOOLTIP_PERMANENT) # Tooltip is too buggy and annoying. Turning it off for now. # @canvas.connect(SEL_QUERY_TIP, method(:tooltip_cb)) end end |
#_new_complex_connection(roomA, exitA) ⇒ Object
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 |
# File 'lib/IFMapper/FXMap.rb', line 732 def _new_complex_connection(roomA, exitA) if @complexConnection.kind_of?(TrueClass) @complexConnection = [roomA, exitA] c = new_connection( roomA, exitA, nil ) status MSG_COMPLEX_CONNECTION_OTHER_EXIT else @sections[@section].delete_connection_at(-1) c = new_connection( @complexConnection[0], @complexConnection[1], roomA, exitA ) if path_find(c) # Do A* path finding to connect both exits @modified = true status MSG_COMPLEX_CONNECTION_DONE else @sections[@section].delete_connection_at(-1) end draw @complexConnection = nil end end |
#_save ⇒ Object
Perform the actual saving of the map
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 |
# File 'lib/IFMapper/FXMap.rb', line 2063 def _save if @complexConnection # If we have an incomplete connection, remove it @sections[@section].delete_connection_at(-1) end if @filename !~ /\.map$/i @filename << '.map' end status "#{MSG_SAVING} '#{@filename}'..." # Make sure we save a valid map. This is mainly a fail-safe # in case of an autosave due to a bug. verify_integrity @version = FILE_FORMAT_VERSION begin f = File.open(@filename, "wb") f.puts Marshal.dump(self) f.close rescue => e status "#{ERR_COULD_NOT_SAVE} '#{@filename}': #{e}" sleep 4 return false end @modified = false status "#{MSG_SAVED} '#{@filename}'." sleep 0.5 return true end |
#add_path_pt(c, x, y) ⇒ Object
Add a new path point to a connection
364 365 366 367 |
# File 'lib/IFMapper/FXMap.rb', line 364 def add_path_pt( c, x, y ) @pmap[x][y] = c c.gpts.push([x, y]) end |
#cannot_automap(why) ⇒ Object
1610 1611 1612 1613 |
# File 'lib/IFMapper/FXMap.rb', line 1610 def cannot_automap(why) w = FXWarningBox.new(@window, "#{ERR_CANNOT_AUTOMAP}\n#{why}") w.execute end |
#center_view_on_room(r) ⇒ Object
Given a room, center scrollwindow so room is visible
1033 1034 1035 1036 1037 |
# File 'lib/IFMapper/FXMap.rb', line 1033 def center_view_on_room(r) xx = (r.xx + W / 2) * @zoom yy = (r.yy + H / 2) * @zoom center_view_on_xy(xx, yy) end |
#center_view_on_xy(xx, yy) ⇒ Object
Given an x and y coordinate for the canvas, center on it
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 |
# File 'lib/IFMapper/FXMap.rb', line 1042 def center_view_on_xy(xx, yy) cw = @scrollwindow.getContentWidth ch = @scrollwindow.getContentHeight w = @scrollwindow.getViewportWidth h = @scrollwindow.getViewportHeight xx -= w / 2 yy -= h / 2 maxx = cw - w / 2 maxy = ch - h / 2 if xx > maxx xx = maxx elsif xx < 0 xx = 0 end if yy > maxy yy = maxy elsif yy < 0 yy = 0 end @scrollwindow.setPosition( -xx, -yy ) end |
#clean_exits(room) ⇒ Object
Clean all paths from path map for a room
1545 1546 1547 1548 1549 1550 |
# File 'lib/IFMapper/FXMap.rb', line 1545 def clean_exits(room) room.exits.each { |c| next if not c clean_path(c) } end |
#clean_path(c) ⇒ Object
Given a connection, clean its path from path map.
252 253 254 |
# File 'lib/IFMapper/FXMap.rb', line 252 def clean_path(c) c.gpts.each { |p| @pmap[p[0]][p[1]] = nil if @pmap[p[0]][p[1]] == c } end |
#clean_room_selection(selection) ⇒ Object
Given a selection of rooms, clear all of them from path map
1525 1526 1527 1528 1529 1530 |
# File 'lib/IFMapper/FXMap.rb', line 1525 def clean_room_selection(selection) selection.each { |r| @pmap[r.x][r.y] = nil clean_exits(r) } end |
#clear_selection ⇒ Object
Clear rooms/connections selected
1079 1080 1081 1082 |
# File 'lib/IFMapper/FXMap.rb', line 1079 def clear_selection @sections[@section].rooms.each { |r| r.selected = false } @sections[@section].connections.each { |r| r.selected = false } end |
#click_type(x, y) ⇒ Object
Given a canvas (mouse) x/y position, return:
false - arrow click true - room click
462 463 464 465 466 467 468 469 470 471 472 |
# File 'lib/IFMapper/FXMap.rb', line 462 def click_type(x, y) x = (x % WW).to_i y = (y % HH).to_i if x >= WS_2 and y >= HS_2 and x <= (W + WS_2) and y <= (H + HS_2) return true else return false end end |
#close_cb ⇒ Object
Close the map. Pop up a warning box to allow saving if map has been modified.
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 |
# File 'lib/IFMapper/FXMap.rb', line 1253 def close_cb() if @modified dlg = FXDialogBox.new( @window.parent, "Warning", DECOR_ALL, 0, 0, 400, 130) # Frame s = FXVerticalFrame.new(dlg, LAYOUT_SIDE_TOP|LAYOUT_FILL_X) f = FXHorizontalFrame.new(s, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y) font = FXFont.new(@window.getApp, "Helvetica", 30) font.create oops = FXLabel.new(f, "!", nil, 0, LAYOUT_SIDE_LEFT|LAYOUT_FILL_X| LAYOUT_CENTER_Y) oops.frameStyle = FRAME_RAISED|FRAME_THICK oops.baseColor = 'dark grey' oops.textColor = 'red' oops.padLeft = oops.padRight = 15 oops.shadowColor = 'black' oops.borderColor = 'white' oops.font = font FXLabel.new(f, "\n#{@name} #{MSG_WAS_MODIFIED}#{MSG_SHOULD_I_SAVE_CHANGES}", nil, 0) # Separator FXHorizontalSeparator.new(s, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE) # Bottom buttons = FXHorizontalFrame.new(s, LAYOUT_SIDE_BOTTOM|FRAME_NONE| LAYOUT_FILL_X|PACK_UNIFORM_WIDTH) # Accept yes = FXButton.new(, BUTTON_YES, nil, dlg, FXDialogBox::ID_ACCEPT, FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X| LAYOUT_RIGHT|LAYOUT_CENTER_Y) yes.connect(SEL_COMMAND) { dlg.close if save @window.close return true else return false end } FXButton.new(, BUTTON_NO, nil, dlg, FXDialogBox::ID_ACCEPT, FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X| LAYOUT_RIGHT|LAYOUT_CENTER_Y) # Cancel FXButton.new(, BUTTON_CANCEL, nil, dlg, FXDialogBox::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X| LAYOUT_RIGHT|LAYOUT_CENTER_Y) yes.setDefault yes.setFocus return false if dlg.execute == 0 end @automap.destroy if @automap @automap = nil @window.close return true end |
#complex_connection ⇒ Object
Start a complex connection
1516 1517 1518 1519 1520 |
# File 'lib/IFMapper/FXMap.rb', line 1516 def complex_connection return if @complexConnection or @complexConnection = true status MSG_COMPLEX_CONNECTION end |
#copy(b) ⇒ Object
Used to copy relevant data from one (temporary) map to another
391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/IFMapper/FXMap.rb', line 391 def copy(b) super(b) if b.kind_of?(FXMap) = b. if b. @filename = b.filename self.zoom = b.zoom = b. @modified = true @complexConnection = nil end end |
#create_pathmap ⇒ Object
Recreate the pathmap based on rooms and connections This routine is used on loading a new map.
240 241 242 243 244 245 246 247 |
# File 'lib/IFMapper/FXMap.rb', line 240 def create_pathmap # First, create an empty grid of width x height empty_pathmap # Then, fill it in with all rooms... @sections[@section].rooms.each { |r| @pmap[r.x][r.y] = r } # And following, add all paths @sections[@section].connections.each { |c| path_find(c) } end |
#current_room ⇒ Object
Return the current active room
1604 1605 1606 1607 1608 |
# File 'lib/IFMapper/FXMap.rb', line 1604 def current_room rooms = @sections[@section].rooms.find_all { |r| r.selected } return nil if rooms.empty? or rooms.size > 1 return rooms[0] end |
#cursor_switch(x, y) ⇒ Object
Based on x,y coordinate, switch mouse icon shape
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 |
# File 'lib/IFMapper/FXMap.rb', line 832 def cursor_switch(x, y) if not ['Use Room Cursor'] @canvas.defaultCursor = @@cursor_arrow return end q = get_quadrant(x, y) case q when 0 @canvas.defaultCursor = @@cursor_n when 1 @canvas.defaultCursor = @@cursor_ne when 2 @canvas.defaultCursor = @@cursor_e when 3 @canvas.defaultCursor = @@cursor_se when 4 @canvas.defaultCursor = @@cursor_s when 5 @canvas.defaultCursor = @@cursor_sw when 6 @canvas.defaultCursor = @@cursor_w when 7 @canvas.defaultCursor = @@cursor_nw else @canvas.defaultCursor = @@cursor_arrow end end |
#cut_selected ⇒ Object
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 |
# File 'lib/IFMapper/FXMap.rb', line 1453 def cut_selected rooms, conns = _cut_selected # Remove room exits pointing to any removed connection if conns conns.each { |c| a = c.roomA b = c.roomB if not rooms.member?(a) a[a.exits.index(c)] = nil end if b and not rooms.member?(b) idx = b.exits.rindex(c) b[idx] = nil if idx end } end if @complexConnection @complexConnection = false status MSG_COMPLEX_CONNECTION_STOPPED end self.modified = true create_pathmap draw end |
#delete_room(r) ⇒ Object
Given a room, delete it
449 450 451 452 453 454 455 |
# File 'lib/IFMapper/FXMap.rb', line 449 def delete_room(r) if @pmap and r.x < @pmap.size and r.y < @pmap.size and r.x >= 0 and r.y >= 0 @pmap[r.x][r.y] = nil end super end |
#delete_room_only(r) ⇒ Object
Given a room, delete it
438 439 440 441 442 443 444 |
# File 'lib/IFMapper/FXMap.rb', line 438 def delete_room_only(r) if @pmap and r.x < @pmap.size and r.y < @pmap.size and r.x >= 0 and r.y >= 0 @pmap[r.x][r.y] = nil end super end |
#delete_section ⇒ Object
Delete current section from map
114 115 116 117 118 119 120 121 |
# File 'lib/IFMapper/FXMap.rb', line 114 def delete_section return if w = FXWarningBox.new(@window, WARN_DELETE_SECTION) return if w.execute == 0 delete_section_at(@section) self.modified = true end |
#delete_selected ⇒ Object
Handle deleting selected rooms and/or connections
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 |
# File 'lib/IFMapper/FXMap.rb', line 1484 def delete_selected return if rooms, conns = _cut_selected # Remove room exits pointing to any removed connection if conns conns.each { |c| a = c.roomA b = c.roomB if not rooms.member?(a) a[a.exits.index(c)] = nil end if b and not rooms.member?(b) idx = b.exits.rindex(c) b[idx] = nil if idx end } end if @complexConnection @complexConnection = false status MSG_COMPLEX_CONNECTION_STOPPED end self.modified = true create_pathmap draw end |
#double_click_cb(selection, event) ⇒ Object
Handle mouse button double clicks in canvas
798 799 800 801 802 803 804 805 |
# File 'lib/IFMapper/FXMap.rb', line 798 def double_click_cb(selection, event) return unless selection # If in navigation mode, we don't allow user to modify map. return if if selection.kind_of?(FXRoom) or selection.kind_of?(FXConnection) selection.properties( self, event ) end end |
#draw(sender = nil, sel = nil, event = nil) ⇒ Object
Draw map
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 |
# File 'lib/IFMapper/FXMap.rb', line 2016 def draw(sender = nil, sel = nil, event = nil) return if @mutex.locked? or not @canvas.created? if not @image.created? # puts "Image was not created. Try again" self.zoom = @zoom end pos = @scrollwindow.position w = @scrollwindow.getViewportWidth h = @scrollwindow.getViewportHeight # The -5 seems to be a bug in fox. don't ask me. cx = -pos[0]-5 cx = 0 if cx < 0 cy = -pos[1]-5 cy = 0 if cy < 0 dc = FXDCWindow.new(@image) dc.setClipRectangle( cx, cy, w, h) dc.font = @font #dc.lineCap = CAP_ROUND draw_background(dc, event) draw_grid(dc, event) if ['Grid Boxes'] if ['Grid Straight Connections'] draw_straight_connections(dc, event) end if ['Grid Diagonal Connections'] draw_diagonal_connections(dc, event) end draw_connections(dc) draw_rooms(dc) dc.end # Blit the off-screen image into canvas dc = FXDCWindow.new(@canvas) dc.setClipRectangle( cx, cy, w, h) dc.drawImage(@image,0,0) dc.end end |
#draw_background(dc, event = nil) ⇒ Object
Clean background to solid color
1911 1912 1913 1914 |
# File 'lib/IFMapper/FXMap.rb', line 1911 def draw_background(dc, event = nil) dc.foreground = ['BG Color'] dc.fillRectangle(0,0, @canvas.width, @canvas.height) end |
#draw_connections(dc) ⇒ Object
Draw connections among rooms
1919 1920 1921 1922 1923 1924 |
# File 'lib/IFMapper/FXMap.rb', line 1919 def draw_connections(dc) dc.lineStyle = LINE_SOLID dc.lineWidth = 3 * @zoom dc.lineWidth = 3 if dc.lineWidth < 3 @sections[@section].connections.each { |c| c.draw(dc, @zoom, ) } end |
#draw_diagonal_connections(dc, event) ⇒ Object
Draw template of diagonal connections in grid background
1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 |
# File 'lib/IFMapper/FXMap.rb', line 1789 def draw_diagonal_connections(dc, event) ww = WW * @zoom hh = HH * @zoom w = W * @zoom h = H * @zoom ws = WS * @zoom hs = HS * @zoom ws_2 = WS_2 * @zoom hs_2 = HS_2 * @zoom maxy = @height - 1 maxx = @width - 1 (0...@height).each { |yy| (0...@width).each { |xx| next if @pmap.at(xx).at(yy).kind_of?(Connection) x = xx * ww y = yy * hh if yy < maxy and xx < maxx # First, draw x1 = x + w + ws_2 y1 = y + h + hs_2 x2 = x1 + ws y2 = y1 + hs dc.drawLine( x1, y1, x2, y2 ) end if yy < maxy and xx > 0 and xx <= maxx # Then, draw / x1 = x + ws_2 y1 = y + h + hs_2 x2 = x1 - ws y2 = y1 + hs dc.drawLine( x2, y2, x1, y1 ) end } } end |
#draw_grid(dc, event = nil) ⇒ Object
Draw template of room squares in background
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 |
# File 'lib/IFMapper/FXMap.rb', line 1883 def draw_grid(dc, event = nil) dc.foreground = "black" dc.lineWidth = 0 dc.lineStyle = LINE_ONOFF_DASH ww = WW * @zoom hh = HH * @zoom w = W * @zoom h = H * @zoom ws_2 = WS_2 * @zoom hs_2 = HS_2 * @zoom (0...@width).each { |xx| (0...@height).each { |yy| next if @pmap.at(xx).at(yy) x = xx * ww + ws_2 y = yy * hh + hs_2 dc.drawRectangle( x, y, w, h ) } } end |
#draw_mapname(dc) ⇒ Object
Draw mapname
1957 1958 1959 1960 1961 1962 1963 1964 |
# File 'lib/IFMapper/FXMap.rb', line 1957 def draw_mapname(dc) fontsize = (24 * @zoom).to_i font = FXFont.new(@window.getApp, ['Font Text'], fontsize) font.create x = @width * WW / 2.0 - @name.size * 24 dc.drawText(x, 30, @name) end |
#draw_room(room) ⇒ Object
Draw a single room (callback used when editing room dialog box)
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 |
# File 'lib/IFMapper/FXMap.rb', line 1929 def draw_room(room) idx = @sections[@section].rooms.index(room) return unless idx dc = FXDCWindow.new(@canvas) dc.font = @font data = { } data['font'] = @font data['objfont'] = @objfont room.draw(dc, @zoom, idx, , data) dc.end end |
#draw_rooms(dc) ⇒ Object
Draw all rooms in current section
1945 1946 1947 1948 1949 1950 1951 1952 |
# File 'lib/IFMapper/FXMap.rb', line 1945 def draw_rooms(dc) data = { } data['font'] = @font data['objfont'] = @objfont @sections[@section].rooms.each_with_index { |room, idx| room.draw(dc, @zoom, idx, , data) } end |
#draw_straight_connections(dc, event) ⇒ Object
Draw template of straight connections in grid background
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 |
# File 'lib/IFMapper/FXMap.rb', line 1838 def draw_straight_connections(dc, event) ww = WW * @zoom hh = HH * @zoom w = W * @zoom h = H * @zoom ws_2 = WS_2 * @zoom hs_2 = HS_2 * @zoom #---- dummy check to catch an ugly bug that I cannot track... create_pathmap if @pmap.size < @width or @pmap[0].size < @height # First, draw horizontal lines (0...@height).each { |yy| (0..@width-2).each { |xx| next if @pmap.at(xx).at(yy).kind_of?(Connection) or @pmap.at(xx+1).at(yy).kind_of?(Connection) x1 = xx * ww + w + ws_2 x2 = (xx + 1) * ww + ws_2 y1 = yy * hh + h / 2 + hs_2 dc.drawLine( x1, y1, x2, y1 ) } } # Then, draw vertical lines (0...@width).each { |xx| (0..@height-2).each { |yy| next if @pmap.at(xx).at(yy).kind_of?(Connection) or @pmap.at(xx).at(yy+1).kind_of?(Connection) x1 = xx * ww + w / 2 + ws_2 y1 = yy * hh + h + hs_2 y2 = (yy + 1) * hh + hs_2 dc.drawLine( x1, y1, x1, y2 ) } } end |
#dump_pathmap ⇒ Object
A simple debugging function that will spit out the path map with a very simple ascii representation.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/IFMapper/FXMap.rb', line 150 def dump_pathmap s = ' ' + ' ' * @width + "\n" m = s * @height (0...@width).each { |x| (0...@height).each { |y| m[y * (@width+2)] = (y % 10).to_s loc = y * (@width+2) + x + 1 if @pmap.at(x).at(y).kind_of?(Connection) m[loc] = '-' elsif @pmap.at(x).at(y).kind_of?(Room) m[loc] = 'R' end } } puts ' 0123456789' * (@width/10) puts m end |
#empty_pathmap ⇒ Object
Reinitialize the pathmap to an empty matrix
227 228 229 230 231 232 233 234 |
# File 'lib/IFMapper/FXMap.rb', line 227 def empty_pathmap # First, create an empty grid of width x height @pmap = Array.new(@width) (0...@width).each { |x| @pmap[x] = Array.new(@height) } return pmap end |
#export_ifm(file) ⇒ Object
Export map as an IFM map file
2110 2111 2112 2113 2114 |
# File 'lib/IFMapper/FXMap.rb', line 2110 def export_ifm(file) require 'IFMapper/IFMWriter' file += '.ifm' if file !~ /\.ifm$/ IFMWriter.new(self, file) end |
#export_inform(file, version = 6) ⇒ Object
Export map as a set of Inform source code files
2147 2148 2149 2150 2151 2152 2153 2154 2155 |
# File 'lib/IFMapper/FXMap.rb', line 2147 def export_inform(file, version = 6) if file =~ /\.inform$/ or version > 6 return export_inform7(file) end require 'IFMapper/InformWriter' file.sub!(/(-\d+)?\.inf/, '') InformWriter.new(self, file) end |
#export_inform7(file) ⇒ Object
Export map as a set of Inform source code files
2129 2130 2131 2132 2133 |
# File 'lib/IFMapper/FXMap.rb', line 2129 def export_inform7(file) require 'IFMapper/Inform7Writer' file.sub!(/\.inform$/, '') Inform7Writer.new(self, file) end |
#export_tads(file) ⇒ Object
Export map as a set of TADS3 source code files
2120 2121 2122 2123 2124 |
# File 'lib/IFMapper/FXMap.rb', line 2120 def export_tads(file) require 'IFMapper/TADSWriter' file.sub!(/(-\d+)?\.t/, '') TADSWriter.new(self, file) end |
#export_trizbort(file) ⇒ Object
Export map as a set of Inform source code files
2138 2139 2140 2141 2142 |
# File 'lib/IFMapper/FXMap.rb', line 2138 def export_trizbort(file) require 'IFMapper/TrizbortWriter' file.sub!(/\.trizbort$/, '') TrizbortWriter.new(self, file) end |
#find_empty_area(rooms) ⇒ Object
Given a list of rooms, find an area in the map where we could place them. If found, return x/y offset so rooms can be moved there. This is used for pasting rooms.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/IFMapper/FXMap.rb', line 200 def find_empty_area(rooms) return nil if rooms.empty? minx = maxx = rooms[0].x miny = maxy = rooms[0].y rooms.each { |r| minx = r.x if r.x < minx maxx = r.x if r.x > maxx miny = r.y if r.y < miny maxy = r.y if r.y > maxy } w = maxx - minx h = maxy - miny # Find an area in pathmap that has w x h empty rooms minx.upto(@width-1-w) { |x| miny.upto(@height-1-h) { |y| if _free_area?(x, y, w, h) return [x - minx, y - miny] end } } return nil end |
#free?(x, y) ⇒ Boolean
Return true or false if map is free at location x, y. If x and y coords are within pathmap, we use it. If not, we will use the brute force search of Map.rb
186 187 188 189 190 191 192 193 |
# File 'lib/IFMapper/FXMap.rb', line 186 def free?(x, y) if @pmap and x >= 0 and y >= 0 and @pmap.size > x and @pmap.at(x).size > y return false if @pmap.at(x).at(y) return true else super end end |
#get_quadrant(ax, ay) ⇒ Object
Given a mouse x/y position to WS/HS, return an index indicating what quadrant it belongs to.
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/IFMapper/FXMap.rb', line 616 def get_quadrant(ax, ay) # First get relative x/y position x = ax % WW y = ay % HH quadrant = nil if x < WS_2 #left if y < HS_2 # top quadrant = 7 elsif y > H + HS_2 # bottom quadrant = 5 else # center quadrant = 6 end elsif x > W + WS_2 # right if y < HS_2 # top quadrant = 1 elsif y > H + HS_2 # bottom quadrant = 3 else # center quadrant = 2 end else #center if y < HS_2 # top quadrant = 0 elsif y > H + HS_2 # bottom quadrant = 4 else # center quadrant = nil end end return quadrant end |
#get_selection ⇒ Object
Return current selection as an array of rooms and an array of connections
1070 1071 1072 1073 1074 |
# File 'lib/IFMapper/FXMap.rb', line 1070 def get_selection rooms = @sections[@section].rooms.find_all { |r| r.selected } conns = @sections[@section].connections.find_all { |r| r.selected } return rooms, conns end |
#help_cb(sender, sel, event) ⇒ Object
Show some help status in status line based on cursor position
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 |
# File 'lib/IFMapper/FXMap.rb', line 876 def help_cb(sender, sel, event) x = (event.last_x / @zoom).to_i y = (event.last_y / @zoom).to_i if @complexConnection cursor_switch(x,y) return end @tooltip_msg = '' sel = to_object(x, y) if sel @canvas.defaultCursor = @@cursor_arrow if sel.kind_of?(Room) @tooltip_msg = sel.name status "\"#{sel.name}\": #{MSG_CLICK_TO_SELECT_AND_MOVE}" elsif sel.kind_of?(Connection) status MSG_CLICK_TOGGLE_ONE_WAY_CONNECTION end else if click_type(x, y) @canvas.defaultCursor = @@cursor_cross status MSG_CLICK_CREATE_ROOM else cursor_switch(x, y) status MSG_CLICK_CREATE_LINK end end end |
#keypress_cb(server, sel, event) ⇒ Object
Handle a keypress
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 |
# File 'lib/IFMapper/FXMap.rb', line 1698 def keypress_cb( server, sel, event) case event.code when KEY_Escape if @complexConnection if @complexConnection.kind_of?(Array) @sections[@section].delete_connection_at(-1) status MSG_COMPLEX_CONNECTION_STOPPED draw end @complexConnection = false end when KEY_BackSpace, KEY_Delete return if delete_selected when KEY_a if event.state & ALTMASK != 0 select_all end when KEY_n if event.state & ALTMASK != 0 clear_selection draw end when KEY_c if event.state & CONTROLMASK != 0 FXMapperWindow::copy_selected(self) draw end when KEY_v if event.state & CONTROLMASK != 0 FXMapperWindow::paste_selected(self) @modified = true draw end # when KEY_u # if event.state & CONTROLMASK != 0 # FXMapperWindow::undo(self) # @modified = true # draw # end when KEY_x return if if event.state & CONTROLMASK != 0 FXMapperWindow::cut_selected(self) @modified = true draw else complex_connection end when KEY_plus zoom_in when KEY_minus zoom_out when KEY_KP_8 move_thru(0) when KEY_KP_9 move_thru(1) when KEY_KP_6 move_thru(2) when KEY_KP_3 move_thru(3) when KEY_KP_2 move_thru(4) when KEY_KP_1 move_thru(5) when KEY_KP_4 move_thru(6) when KEY_KP_7 move_thru(7) when KEY_Up move_to(0) when KEY_Down move_to(4) when KEY_Left move_to(6) when KEY_Right move_to(2) when KEY_End move_to(5) when KEY_Home move_to(7) when KEY_Page_Up move_to(1) when KEY_Page_Down move_to(3) end end |
#lmb_click_cb(sender, sel, event) ⇒ Object
Handle left mouse button click
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
# File 'lib/IFMapper/FXMap.rb', line 1155 def lmb_click_cb(sender, sel, event) x = (event.last_x / @zoom).to_i y = (event.last_y / @zoom).to_i if event.state & ALTMASK != 0 mmb_click_cb(sender, sel, event) return end selection = to_object(x, y) if event.state & SHIFTMASK != 0 @mouseButton = LEFTBUTTON @canvas.grab @dx, @dy = [ x, y ] return if not selection end if event.click_count == 2 double_click_cb(selection, event) return end unless selection clear_selection # If in navigation mode, we don't allow user to modify map. return if # if we did not select anything, check to see if we # clicked in a room area or connection area. if click_type(x, y) return if @complexConnection # Add a new room roomB = @sections[@section].rooms[-1] roomA = new_xy_room( x, y ) if roomB and roomA and ['Automatic Connection'] # check to see if rooms are next to each other # if so, try to connect them (assuming there's no connection there # already). exitB = roomB.next_to?(roomA) if exitB and roomB.exits[exitB] == nil new_connection( roomB, exitB, roomA ) end end else # Add a new connection if @complexConnection new_complex_connection(x, y) else # Add a new simple connection (plus rooms if needed) if event.state & CONTROLMASK != 0 exitA = get_quadrant(x, y) roomA, roomB, a, b = quadrant_to_rooms( exitA, x, y ) if not roomA new_xy_connection( x, y ) else if a and roomA @complexConnection = [roomA, exitA] new_connection( roomA, exitA, nil ) _new_complex_connection( roomA, exitA ) end end else new_xy_connection( x, y ) end end end else if selection.kind_of?(Connection) and selection.selected # Toggle arrow direction # If in navigation mode, we don't allow user to modify map. return if selection.toggle_direction draw return else if event.state & SHIFTMASK == 0 and event.state & CONTROLMASK == 0 clear_selection end # Select the stuff selection.update_properties(self) if event.state & CONTROLMASK != 0 selection.selected ^= true # toggle selection else selection.selected = true end end end draw(sender, sel, event) end |
#marshal_dump ⇒ Object
Used for saving class with Marshal
384 385 386 |
# File 'lib/IFMapper/FXMap.rb', line 384 def marshal_dump [ @zoom, , ] + super end |
#marshal_load(variables) ⇒ Object
Used for loading class with Marshal
372 373 374 375 376 377 378 379 |
# File 'lib/IFMapper/FXMap.rb', line 372 def marshal_load(variables) @zoom = variables.shift = variables.shift = variables.shift super @modified = false @complexConnection = nil end |
#max_width(opts) ⇒ Object
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1182 def max_width(opts) max_width=0 @sections.each_with_index{ |sect, idx| maxx = sect.svg_width(opts) if(maxx > max_width) max_width = maxx end if DEBUG_OUTPUT; puts("section=" + idx.to_s + ":maxx=" + maxx.to_s) end } return max_width end |
#mmb_click_cb(server, sel, event) ⇒ Object
Handle middle mouse button click in canvas
932 933 934 935 936 |
# File 'lib/IFMapper/FXMap.rb', line 932 def mmb_click_cb(server, sel, event) @canvas.grab @dx = @dy = 0 @mouseButton = MIDDLEBUTTON end |
#mmb_release_cb(server, sel, event) ⇒ Object
Handle release of middle mouse button
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 |
# File 'lib/IFMapper/FXMap.rb', line 1017 def mmb_release_cb(server, sel, event) if @mouseButton @canvas.ungrab @canvas.dragCursor = @@cursor_arrow if @mouseButton == LEFTBUTTON draw else @canvas.repaint end @mouseButton = nil end end |
#motion_cb(server, sel, event) ⇒ Object
Handle mouse motion in canvas
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 |
# File 'lib/IFMapper/FXMap.rb', line 991 def motion_cb(server, sel, event) if @mouseButton == MIDDLEBUTTON @canvas.dragCursor = @@cursor_move pos = @scrollwindow.position dx = event.last_x - event.win_x dy = event.last_y - event.win_y if (dx != 0 or dy != 0) and !(dx == @dx and dy == @dy) pos[0] += dx pos[1] += dy @dx = dx @dy = dy @scrollwindow.setPosition(pos[0], pos[1]) @canvas.repaint end elsif @mouseButton == LEFTBUTTON x = (event.last_x / @zoom).to_i y = (event.last_y / @zoom).to_i select_rectangle( @dx, @dy, x, y ) else help_cb(server, sel, event) end end |
#mousewheel_cb(sender, sel, event) ⇒ Object
zoom in/out based on mousewheel, keeping position relative to cursor position
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 |
# File 'lib/IFMapper/FXMap.rb', line 910 def mousewheel_cb(sender, sel, event) case event.code when -120 # Hmm, there does not seem to be constants for these zoom_out # @scrollwindow.setPosition( -x, -y ) when 120 # Hmm, there does not seem to be constants for these # pos = @scrollwindow.position # w = @scrollwindow.maxChildWidth # h = @scrollwindow.maxChildHeight #p @scrollwindow.range # puts "pos: #{pos[0]} #{pos[1]}" # x = event.last_x # y = event.last_y # puts "event: #{x} #{y}" zoom_in # @scrollwindow.setPosition( -x, -y ) end end |
#move_thru(idx) ⇒ Object
Move through an exit into another room. If exit is empty, create a new neighboring room.
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 |
# File 'lib/IFMapper/FXMap.rb', line 1660 def move_thru(idx) room = current_room return if not room exit = room[idx] if exit room.selected = false if room == exit.roomA roomB = exit.roomB else roomB = exit.roomA end roomB.selected = true draw else return if x, y = room.x, room.y dx, dy = Room::DIR_TO_VECTOR[idx] x += dx y += dy x = 0 if x < 0 y = 0 if y < 0 x = @width-1 if x > @width-1 y = @height-1 if y > @height-1 if not @pmap.at(x).at(y).kind_of?(Room) room.selected = false roomB = new_xy_room(x * WW, y * HH) exitB = roomB.next_to?(room) if exitB and roomB.exits[exitB] == nil new_connection( roomB, exitB, room ) end draw end end end |
#move_to(idx) ⇒ Object
Move selected rooms in one of the 8 cardinal directions.
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 |
# File 'lib/IFMapper/FXMap.rb', line 1627 def move_to(idx) return if selection = @sections[@section].rooms.find_all { |r| r.selected } return if selection.empty? clean_room_selection(selection) dx, dy = Room::DIR_TO_VECTOR[idx] # Check that all nodes can be moved in the specified direction selection.each { |r| x = r.x + dx y = r.y + dy if x < 0 or y < 0 or x >= @width or y >= @height or @pmap.at(x).at(y).kind_of?(Room) store_room_selection(selection) dir = Room::DIRECTIONS[idx] status "#{ERR_CANNOT_MOVE_SELECTION} #{dir}." return end } selection.each { |r| r.x += dx r.y += dy } update_exits(selection) draw end |
#navigation_warning ⇒ Object
Give user some warning if he tries to modify a read-only mode.
1618 1619 1620 1621 |
# File 'lib/IFMapper/FXMap.rb', line 1618 def w = FXWarningBox.new(@window, ERR_READ_ONLY_MAP) w.execute end |
#new_complex_connection(x, y) ⇒ Object
Add a new complex connection (or its first point)
720 721 722 723 724 725 726 727 728 729 730 |
# File 'lib/IFMapper/FXMap.rb', line 720 def new_complex_connection( x, y ) exitA = get_quadrant(x, y) unless exitA raise "not a connection" end roomA, roomB, a, b = quadrant_to_rooms( exitA, x, y ) unless a and roomA and roomA[exitA] == nil return end _new_complex_connection(roomA, exitA) end |
#new_room(x, y) ⇒ Object
Create a new room for the current section
406 407 408 409 410 |
# File 'lib/IFMapper/FXMap.rb', line 406 def new_room(x, y) @modified = true r = @sections[@section].new_room(x, y) return r end |
#new_section ⇒ Object
Add a new section to map and make it current
126 127 128 129 130 |
# File 'lib/IFMapper/FXMap.rb', line 126 def new_section return if @sections.push( FXSection.new ) @section = @sections.size - 1 end |
#new_xy_connection(x, y) ⇒ Object
Add a new room connection among contiguous rooms.
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 |
# File 'lib/IFMapper/FXMap.rb', line 755 def new_xy_connection( x, y ) exitA = get_quadrant(x, y) unless exitA raise "not a connection" end # Then, get rooms being connected roomA, roomB, a, b = quadrant_to_rooms( exitA, x, y ) return unless a # User click outside map if ['Create on Connection'] roomA = new_xy_room( a[0], a[1] ) unless roomA roomB = new_xy_room( b[0], b[1] ) unless roomB end return nil unless roomA and roomB if roomA == roomB raise "error: same room connection" end @modified = true if roomA and exitA # get old connection if roomA[exitA] c = roomA[exitA] delete_connection(c) if c.roomB == nil end exitB = (exitA + 4) % 8 if roomB[exitB] c = roomB[exitB] delete_connection(c) if c.roomB == nil end end begin new_connection( roomA, exitA, roomB ) rescue Section::ConnectionError end end |
#new_xy_room(x, y) ⇒ Object
Function used to add a new room. x and y are absolute pixel positions in canvas.
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/IFMapper/FXMap.rb', line 416 def new_xy_room(x, y) x = x / WW y = y / HH r = new_room(x, y) @pmap[x][y] = r r.selected = true if ['Edit on Creation'] if not r.modal_properties(self) @sections[@section].delete_room(r) @pmap[x][y] = nil return nil end end update_roomlist return r end |
#next_section ⇒ Object
Go to next section (if any)
90 91 92 93 |
# File 'lib/IFMapper/FXMap.rb', line 90 def next_section self.section = @section + 1 _changed end |
#num_sections ⇒ Object
1203 1204 1205 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1203 def num_sections() return @sections.length end |
#path_find(c) ⇒ Object
Given a connection, create the path for it, if not a simple connection. Also, add the paths to pathmap.
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/IFMapper/FXMap.rb', line 266 def path_find(c) unless c.complex? c.pts = c.gpts = [] c.failed = false return true end # Complex path... Generate points. a, b = c.room dirA, dirB = c.dirs raise "A connection not found #{c} at #{a}" unless dirA raise "B connection not found #{c} at #{b}" unless dirB vA = FXRoom::DIR_TO_VECTOR[dirA] vB = FXRoom::DIR_TO_VECTOR[dirB] pA = [ a.x + vA[0], a.y + vA[1] ] pB = [ b.x + vB[0], b.y + vB[1] ] c.gpts = [] c.pts = [] # Check for the special case of looping path (path that begins and # returns to same exit) if a == b and dirA == dirB pt = a.corner(c, 1, dirA) n = 1.0 / Math.sqrt(vA[0] * vA[0] + vA[1] * vA[1]) vA = [ vA[0] * n, vA[1] * n ] c.pts.push( [ pt[0], pt[1] ] ) pA = [ pt[0] + vA[0] * 20, pt[1] + vA[1] * 20 ] c.pts.push( [pA[0], pA[1]] ) pB = [ pA[0] + vA[1] * 20, pA[1] - vA[0] * 20 ] c.pts.push( [pB[0], pB[1]] ) pC = [ pB[0] - vA[0] * 20, pB[1] - vA[1] * 20 ] c.pts.push( [pC[0], pC[1]] ) c.dir = Connection::AtoB return true end # Now check if start or goal are fully blocked. If so, # fail quickly if pA[0] < 0 or pA[0] >= @width or pB[0] < 0 or pB[0] >= @width or pA[1] < 0 or pA[1] >= @height or pB[1] < 0 or pB[1] >= @height or @pmap.at(pA[0]).at(pA[1]).kind_of?(Room) or @pmap.at(pB[0]).at(pB[1]).kind_of?(Room) remove_connection(c) return false end if (pA[0] - pB[0]).abs > 30 or (pA[1] - pB[1]).abs > 30 c.failed = true return end # No, okay, we need to do true A* path finding c.failed = false aStar = AStar.new MapNode::map(@pmap) start = MapNode.new( pA[0], pA[1] ) goal = MapNode.new( pB[0], pB[1] ) aStar.goals( start, goal ) while aStar.search_step == AStar::SEARCH_STATE_SEARCHING end # Oops, AStar failed. Not a clean path if aStar.state == AStar::SEARCH_STATE_FAILED remove_connection(c) return false end # We succeeded. Get the path c.failed = false c.gpts = aStar.path # Put path in pathmap so subsequent paths will try to avoid crossing it. c.gpts.each { |p| @pmap[p[0]][p[1]] = c } # Okay, we have a valid path. # Create real path in display coordinates now... # Start with a's corner pt = a.corner(c, 1, dirA) c.pts.push( [ pt[0], pt[1] ] ) # Then, add each grid point we calculated c.gpts.each { |p| x = p[0] * WW + WW / 2 y = p[1] * HH + HH / 2 c.pts.push([x, y]) } # And end with b's corner pt = b.corner(c, 1, dirB) return c.pts.push([pt[0], pt[1]]) end |
#pdf_draw_mapname(pdf, opts) ⇒ Object
453 454 455 456 457 458 459 |
# File 'lib/IFMapper/PDFMapExporter_prawn.rb', line 453 def pdf_draw_mapname( pdf, opts ) return if not @name or @name == '' pdf.text( @name, :font_size => 24, :justification => :center ) end |
#pdf_draw_sections(pdf, opts) ⇒ Object
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
# File 'lib/IFMapper/PDFMapExporter_prawn.rb', line 461 def pdf_draw_sections( pdf, opts ) old_section = @section page = -1 @sections.each_with_index { |sect, idx| if page != sect.page page = sect.page pdf.start_new_page if page > 1 pdf_draw_mapname( pdf, opts ) end @section = idx # For each page, we need to regenerate the pathmap so that complex # paths will come out ok. create_pathmap # Now, we draw it sect.pdf_draw(pdf, opts, @name, pdflocationnos) } # Restore original viewing page @section = old_section create_pathmap end |
#pdf_export(pdffile = Dir::tmpdir + "/ifmap.pdf", printer = nil) ⇒ Object
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 |
# File 'lib/IFMapper/PDFMapExporter_prawn.rb', line 484 def pdf_export(pdffile = Dir::tmpdir + "/ifmap.pdf", printer = nil) # PRE: Let's set the PDF paper size to user's choice paper = BOX_PDF_PAGE_SIZE_TEXT[pdfpapersize] if printer case printer.mediasize when FXPrinter::MEDIA_LETTER paper = 'LETTER' when FXPrinter::MEDIA_LEGAL paper = 'LEGAL' when FXPrinter::MEDIA_A4 paper = 'A4' # Valid when FXPrinter::MEDIA_ENVELOPE paper = 'ENVELOPE' when FXPrinter::MEDIA_CUSTOM raise "Sorry, custom paper not supported" end end # Open a new PDF writer with paper selected pdf = Prawn::Document.new :page_size => paper = .dup ww = PDF_ROOM_WIDTH + PDF_ROOM_WS hh = PDF_ROOM_HEIGHT + PDF_ROOM_HS .merge!( { 'ww' => ww, 'hh' => hh, 'w' => PDF_ROOM_WIDTH, 'h' => PDF_ROOM_HEIGHT, 'ws' => PDF_ROOM_WS, 'hs' => PDF_ROOM_HS, 'ws_2' => PDF_ROOM_WS / 2.0, 'hs_2' => PDF_ROOM_HS / 2.0, 'margin' => PDF_MARGIN, 'margin_2' => PDF_MARGIN / 2.0, 'width' => (pdf.margin_box.width / ww).to_i - 1, 'height' => (pdf.margin_box.height / hh).to_i - 1, } ) begin ratio = pdf.margin_box.height / pdf.margin_box.width.to_f; # See if it is possible to pack several map sections (sections) into # a single print page. loop do num = pack_sections( ['width'], ['height'] ) if num > 0 break end width += 1 height = (width * ratio).to_i + 1; end pdf_draw_sections(pdf, ) if pdffile !~ /\.pdf$/ pdffile << ".pdf" end status "Exporting PDF file '#{pdffile}'" pdf.render_file pdffile rescue => e p e p e.backtrace raise e end end |
#previous_section ⇒ Object
Go to previous section (if any)
82 83 84 85 |
# File 'lib/IFMapper/FXMap.rb', line 82 def previous_section self.section = @section - 1 _changed end |
#print(printer) ⇒ Object
Print map
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 |
# File 'lib/IFMapper/FXMap.rb', line 1969 def print(printer) # dc = FXDCPrint.new(@window.getApp) require 'IFMapper/MapPrinting' require 'IFMapper/FXDCPostscript' oldzoom = @zoom oldsection = @section self.zoom = 1.0 num = pack_sections( @width, @height ) begin dc = FXDCPostscript.new(@window.getApp) xmax = @width * WW ymax = @height * HH dc.setContentRange(0, 0, xmax, ymax) dc.beginPrint(printer) { page = -1 0.upto(@sections.size-1) { |p| self.section = p clear_selection if page != sect.page dc.beginPage(sect.page) draw_mapname( dc ) end dc.lineCap = CAP_ROUND # draw_grid(dc) draw_connections(dc) draw_rooms(dc) if page != sect.page page = sect.page dc.endPage() end } } rescue => e status "#{e}" end self.section = oldsection self.zoom = oldzoom draw end |
#properties ⇒ Object
Open the map’s property window
2190 2191 2192 2193 2194 2195 2196 |
# File 'lib/IFMapper/FXMap.rb', line 2190 def properties if not @@win @@win = FXMapDialogBox.new(@window) end @@win.copy_from(self) @@win.show end |
#quadrant_to_rooms(q, x, y) ⇒ Object
Given an x,y absolute position corresponding to a connection, return connected rooms (if any).
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
# File 'lib/IFMapper/FXMap.rb', line 666 def quadrant_to_rooms( q, x, y ) maxX = @width * WW maxY = @height * HH # First check if user tried adding a connection # at the edges of the map. If so, return empty stuff. if x < WS_2 or y < HS_2 or x > maxX - WS_2 or y > maxY - HS_2 return [nil, nil, nil, nil] end x1 = x2 = x y1 = y2 = y case q when 0, 4 y1 -= HS y2 += HS when 1, 5 x1 -= WS x2 += WS y1 += HS y2 -= HS when 2, 6 x1 -= WS x2 += WS when 3, 7 x1 -= WS y1 -= HS x2 += WS y2 += HS end case q when 0, 5, 6, 7 x1, x2 = x2, x1 y1, y2 = y2, y1 end roomA = to_room(x1, y1) roomB = to_room(x2, y2) # Oops, user tried to create rooms where we already # have a complex connection. Don't create anything, then. if roomA.kind_of?(Connection) or (roomB.kind_of?(Connection) and not @complexConnection) return [roomA, roomB, nil, nil] end return [roomA, roomB, [x1, y1], [x2, y2]] end |
#remove_connection(c) ⇒ Object
Remove a connection from map, since path creation failed.
259 260 261 262 |
# File 'lib/IFMapper/FXMap.rb', line 259 def remove_connection(c) c.failed = true status "#{ERR_PATH_FOR_CONNECTION} #{c} #{ERR_IS_BLOCKED}." end |
#rename_section ⇒ Object
Popup the section properties to allow renaming it
106 107 108 109 |
# File 'lib/IFMapper/FXMap.rb', line 106 def rename_section @sections[@section].properties(self) self.modified = true end |
#rmb_click_cb(sender, sel, event) ⇒ Object
Handle right mouse button click
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 |
# File 'lib/IFMapper/FXMap.rb', line 1114 def rmb_click_cb(sender, sel, event) rooms, links = get_selection = nil if not links.empty? and links.size == 1 c = links[0] a = c.roomA b = c.roomB = FXMenuPane.new(@window) if c.dir == Connection::AtoB cmd = FXMenuCommand.new(, MENU_FLIP_DIRECTION) cmd.connect(SEL_COMMAND) { c.flip; draw } FXMenuSeparator.new() end = FXMenuPane.new(@window) old_idx = a.exits.index(c) 0.upto(7) { |idx| ( , c, a, idx, old_idx ) } FXMenuCascade.new(, a.name, nil, ) if b = FXMenuPane.new(@window) old_idx = b.exits.rindex(c) 0.upto(7) { |idx| ( , c, b, idx, old_idx ) } FXMenuCascade.new(, b.name, nil, ) end end if .create .popup(nil, event.root_x, event.root_y) @window.getApp.runModalWhileShown() end end |
#rmb_link_menu(submenu, c, room, idx, old_idx) ⇒ Object
Add a proper link submenu option for an exit
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 |
# File 'lib/IFMapper/FXMap.rb', line 1087 def (, c, room, idx, old_idx) return if room[idx] == c dir = Room::DIRECTIONS[idx] dir = dir.upcase if room[idx] cmd = FXMenuCommand.new(, "#{MENU_SWITCH_WITH_LINK} #{dir}") cmd.connect(SEL_COMMAND) { c2 = room[idx] room[old_idx] = c2 room[idx] = c create_pathmap draw } else cmd = FXMenuCommand.new(, "#{MENU_MOVE_LINK} #{dir}") cmd.connect(SEL_COMMAND) { room[old_idx] = nil room[idx] = c create_pathmap draw } end end |
#save ⇒ Object
Save the map. If the map’s filename is not defined, call save_as
2098 2099 2100 2101 2102 2103 2104 |
# File 'lib/IFMapper/FXMap.rb', line 2098 def save unless @filename save_as else _save end end |
#save_as ⇒ Object
Save the map under a new filename, bringing up a file requester
2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 |
# File 'lib/IFMapper/FXMap.rb', line 2160 def save_as require 'IFMapper/FXMapFileDialog' file = FXMapFileDialog.new(@window, "#{MSG_SAVE_MAP} #{@name}", FXMapFileDialog::KNOWN_SAVE_EXTENSIONS).filename if file != '' if File.exist?(file) dlg = FXWarningBox.new(@window, "#{file}\n#{WARN_OVERWRITE_MAP}") return if dlg.execute == 0 end case file when /\.inform$/, /\.inf$/ export_inform(file) when /\.ifm$/ export_ifm(file) when /\.t$/ export_tads(file) when /\.trizbort$/ export_trizbort(file) else @filename = file return _save end end return false end |
#section=(x) ⇒ Object
Jump to a certain section #
72 73 74 75 76 77 |
# File 'lib/IFMapper/FXMap.rb', line 72 def section=(x) clear_selection super @complexConnection = false _changed end |
#select_all ⇒ Object
Select all connections and rooms
135 136 137 138 139 140 141 142 143 144 |
# File 'lib/IFMapper/FXMap.rb', line 135 def select_all sect = sections[section] sect.rooms.each { |r| r.selected = true } sect.connections.each { |c| c.selected = true } draw end |
#select_rectangle(x1, y1, x2, y2) ⇒ Object
Select all rooms and connections within (drag) rectangle
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 |
# File 'lib/IFMapper/FXMap.rb', line 941 def select_rectangle(x1, y1, x2, y2) x1, x2 = x2, x1 if x2 < x1 y1, y2 = y2, y1 if y2 < y1 x = x1 * zoom y = y1 * zoom w = x2 - x1 h = y2 - y1 x1 = ((x1 + WS_2) / WW).floor y1 = ((y1 + HS_2) / HH).floor x2 = ((x2 - WS_2) / WW).ceil y2 = ((y2 - HS_2) / HH).ceil @sections[@section].rooms.each { |r| if r.x >= x1 and r.x <= x2 and r.y >= y1 and r.y <= y2 r.selected = true r.update_properties(self) else r.selected = false end } @sections[@section].connections.each { |c| next if not c.roomB a = c.roomA b = c.roomB if (a.x >= x1 and a.x <= x2 and a.y >= y1 and a.y <= y2) or (b.x >= x1 and b.x <= x2 and b.y >= y1 and b.y <= y2) c.selected = true c.update_properties(self) else c.selected = false end } draw dc = FXDCWindow.new(@canvas) dc.function = BLT_NOT_SRC_XOR_DST dc.drawRectangle(x, y, w * @zoom, h * @zoom) dc.end end |
#show_itemlist ⇒ Object
1562 1563 1564 1565 1566 1567 1568 1569 1570 |
# File 'lib/IFMapper/FXMap.rb', line 1562 def show_itemlist if @@itemlist @@itemlist.copy_from(self) else require 'IFMapper/FXItemList' @@itemlist = FXItemList.new(self) end @@itemlist.show end |
#show_roomlist ⇒ Object
1552 1553 1554 1555 1556 1557 1558 1559 1560 |
# File 'lib/IFMapper/FXMap.rb', line 1552 def show_roomlist if @@roomlist @@roomlist.copy_from(self) else require 'IFMapper/FXRoomList' @@roomlist = FXRoomList.new(self) end @@roomlist.show end |
#start_automap ⇒ Object
2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 |
# File 'lib/IFMapper/FXMap.rb', line 2206 def start_automap if @automap stop_automap end require 'IFMapper/FXMapFileDialog' file = FXMapFileDialog.new(@window, MSG_LOAD_TRANSCRIPT, [ EXT_TRANSCRIPT, EXT_ALL_FILES ]).filename return if file == '' require 'IFMapper/TranscriptReader' begin @automap = TranscriptReader.new(self, file) @automap.properties(true) @automap.start rescue Errno::EACCES, Errno::ENOENT => e dlg = FXWarningBox.new(@window, "#{ERR_CANNOT_OPEN_TRANSCRIPT}\n#{e}") dlg.execute return rescue => e puts e.backtrace dlg = FXWarningBox.new(@window, "#{ERR_PARSE_TRANSCRIPT}\n#{e}\n#{e.backtrace}") dlg.execute raise end create_pathmap draw update_title end |
#status(msg) ⇒ Object
Spit out a new message to the status line.
822 823 824 825 826 827 |
# File 'lib/IFMapper/FXMap.rb', line 822 def status(msg) mw = @window.parent.parent = mw.children.find() { |x| x.kind_of?(FXStatusBar) } s = .statusLine s.normalText = s.text = msg end |
#stop_automap ⇒ Object
2198 2199 2200 2201 2202 2203 2204 |
# File 'lib/IFMapper/FXMap.rb', line 2198 def stop_automap return unless @automap @automap.destroy @automap = nil GC.start update_title end |
#store_room_selection(selection) ⇒ Object
Given a selection of rooms, clear all of them from path map
1535 1536 1537 1538 1539 1540 |
# File 'lib/IFMapper/FXMap.rb', line 1535 def store_room_selection(selection) selection.each { |r| @pmap[r.x][r.y] = r } update_exits(selection) end |
#svg_draw_current_section(opts, svgfile) ⇒ Object
1102 1103 1104 1105 1106 1107 1108 1109 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1102 def svg_draw_current_section( opts, svgfile ) # Draw current section only to individual file svg_draw_section_separate(opts, @section, svgfile) status MSG_SVG_EXPORT_COMPLETED end |
#svg_draw_section_separate(opts, idx, svgfile) ⇒ Object
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1068 def svg_draw_section_separate( opts, idx, svgfile ) # Called from both: # Draw current section only to individual file # Draw all sections into individual files svgfilename = String::new(str=svgfile) @section = idx create_pathmap if DEBUG_OUTPUT; printf("svg_draw_sections_separate: filename = %s\r\n", svgfilename.to_s()) end # Remove .svg from end of filename if it is there. if svgfilename =~ /\.svg$/ svgfilename = svgfilename[0..-5]; end # Append the section number. svgfilename << "-section" << (idx + 1).to_s() if DEBUG_OUTPUT; printf("svg_draw_separate: filename = %s\r\n", svgfilename.to_s()) end # Add .svg back onto the end of the filename. svgfilename << ".svg" if DEBUG_OUTPUT; printf("svg_draw_separate: filename = %s\r\n", svgfilename.to_s()) end status "#{MSG_SVG_EXPORTING} '#{svgfilename}'" @sections[idx].svg_draw_separate( opts, svgfilename, idx, @name, @creator, max_width(opts)) end |
#svg_draw_sections(opts, svgfile) ⇒ Object
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1122 def svg_draw_sections( opts, svgfile ) # Draw all sections in one SVG file if DEBUG_OUTPUT; puts "svg::FXMap::svg_draw_sections" end if DEBUG_OUTPUT; printf("svg::FXMap::svg_draw_sections:@section=%s\r\n", @section) end x = opts['name_x'] + opts['margin'] y = opts['name_y'] + opts['margin'] font_size = opts['name_font_size'] svg = SVGUtilities::new_svg_doc(max_width(opts), total_height(opts)) if opts['compass_size'] > 0 svg = SVGUtilities::add_compass(svg) end if SVGUtilities::should_draw_interactive(opts) == true svg = SVGUtilities::svg_add_script(svg, opts) end svg, x, y = SVGUtilities::add_titles(svg, opts, x, y, font_size, @name, @creator) @sections.each_with_index { |sect, idx| @section = idx # For each page, we need to regenerate the pathmap so that complex # paths will come out ok. create_pathmap # Now, we draw it outx, outy = sect.svg_draw(svg, opts, x, y, @name, idx) if DEBUG_OUTPUT; puts "svg_draw_sections: section gap (hh*2) = #{opts['hh'] * 2}" end y = y + outy + (opts['hh'] * 2) } create_pathmap svg.root.attributes["height"] = y svg = SVGUtilities::add_background(svg, max_width(opts).to_s, y.to_s, File.basename(svgfile, ".*")) if svgfile !~ /\.svg$/ svgfile << ".svg" end status "#{MSG_SVG_EXPORTING} '#{svgfile}'" formatter = REXML::Formatters::Pretty.new(2) formatter.compact = true formatter.width = 99999999 file = File.open(svgfile, "w") formatter.write(svg, file) file.close status MSG_SVG_EXPORT_COMPLETED end |
#svg_draw_sections_separate(opts, svgfile) ⇒ Object
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1111 def svg_draw_sections_separate( opts, svgfile ) # Draw all sections into individual files @sections.each_with_index { |sect, idx| svg_draw_section_separate(opts, idx, svgfile) } status MSG_SVG_EXPORT_COMPLETED end |
#svg_export(svgfile, printer = nil) ⇒ Object
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1207 def svg_export(svgfile, printer = nil) if DEBUG_OUTPUT; puts "svg::FXMap::svg_export" end = .dup ww = SVG_ROOM_WIDTH + SVG_ROOM_WS hh = SVG_ROOM_HEIGHT + SVG_ROOM_HS = { 'ww' => ww, 'hh' => hh, 'w' => SVG_ROOM_WIDTH, 'h' => SVG_ROOM_HEIGHT, 'ws' => SVG_ROOM_WS, 'hs' => SVG_ROOM_HS, 'ws_2' => SVG_ROOM_WS / 2.0, 'hs_2' => SVG_ROOM_HS / 2.0, 'margin' => 10, 'margin_2' => 5, 'text_max_chars' => 20, 'text_line_spacing' => 2, 'text_margin' => 5, 'room_line_width' => 2, 'room_line_colour' => "black", 'room_font_size' => 8, 'objects_font_size' => 6, 'objects_width' => 140, 'room_num_font_size' => 6, 'print_room_nums' => true, 'num_line_width' => 1, 'num_line_colour' => "black", 'num_fill_colour' => "lightgreen", 'conn_line_width' => 2, 'conn_line_colour' => "black", 'door_line_width' => 2, 'door_line_colour' => "forestgreen", 'arrow_line_width' => 1, 'arrow_line_colour' => "black", 'arrow_fill_colour' => "black", 'name_font_size' => 18, 'name_x' => 0, 'name_y' => 0, 'name_line_spacing' => 4, 'print_title' => true, 'print_creator' => true, 'print_date' => true, 'creator_prefix' => MSG_SVG_CREATOR_PREFIX, 'draw_objects' => true, 'draw_tasks' => true, 'draw_comments' => true, 'draw_description' => true, 'draw_roomnames' => true, 'draw_connections' => true, 'corner_size' => 15, 'corner_line_colour' => "black", 'corner_line_width' => 1, 'corner_fill_colour' => "lightgreen", 'objs_line_colour' => "black", 'objs_line_width' => 1, 'objs_fill_colour' => "lightgreen", 'print_section_names' => true, 'section_name_prefix' => "Section: ", 'split_sections' => false, 'draw_sectioncomments' => true, 'compass_size' => 3, 'font_width_fiddle' => 1.5, 'selected_elements_only' => false, 'text_for_selected_only' => false, 'current_section_only' => false } .merge!() begin if ['current_section_only'] == true # Draw current section only to individual file svg_draw_current_section(, svgfile) else if ['split_sections'] == false # Draw all sections in one SVG file svg_draw_sections(, svgfile) else # Draw all sections into individual files svg_draw_sections_separate(, svgfile) end end rescue => e p e p e.backtrace raise e end end |
#to_object(x, y) ⇒ Object
Given a mouse click x/y position, return object(s) if any or nil
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
# File 'lib/IFMapper/FXMap.rb', line 483 def to_object(x, y) exitA = get_quadrant(x, y) unless exitA # Not in arrow section, return element based on pmap # can be a room or complex arrow connection. xx = x / WW yy = y / HH return nil if xx >= @width or yy >= @height return @pmap.at(xx).at(yy) else # Possible arrow @sections[@section].connections.each { |c| a = c.roomA b = c.roomB next if not b and @complexConnection if c.gpts.size > 0 2.times { |t| if t == 0 r = a dir = r.exits.index(c) else r = b dir = r.exits.rindex(c) end next if not r x1, y1 = r.corner(c, 1, dir) v = FXRoom::DIR_TO_VECTOR[dir] x2 = x1 + v[0] * WS y2 = y1 + v[1] * HS if x1 == x2 x1 -= W / 2 x2 += W / 2 end if y1 == y2 y1 -= H / 2 y2 += H / 2 end x1, x2 = x2, x1 if x2 < x1 y1, y2 = y2, y1 if y2 < y1 if x >= x1 and x <= x2 and y >= y1 and y < y2 return c end } else x1, y1 = a.corner(c, 1, a.exits.index(c)) if b x2, y2 = b.corner(c, 1, b.exits.rindex(c)) else dir = a.exits.index(c) v = FXRoom::DIR_TO_VECTOR[dir] x2 = x1 + v[0] * WS y2 = y1 + v[1] * HS end x1, x2 = x2, x1 if x2 < x1 y1, y2 = y2, y1 if y2 < y1 if x1 == x2 x1 -= W / 2 x2 += W / 2 end if y1 == y2 y1 -= H / 2 y2 += H / 2 end if x >= x1 and x <= x2 and y >= y1 and y < y2 return c end end } return nil end return nil end |
#to_room(x, y) ⇒ Object
Given an x and y canvas position, return room object, complex connection or nil
476 477 478 479 480 |
# File 'lib/IFMapper/FXMap.rb', line 476 def to_room(x,y) xx = x / WW yy = y / HH return @pmap.at(xx).at(yy) end |
#tooltip_cb(sender, id, ptr) ⇒ Object
Based on mouse position on canvas, create a tooltip
863 864 865 866 867 868 869 870 |
# File 'lib/IFMapper/FXMap.rb', line 863 def tooltip_cb(sender, id, ptr) if @zoom < 0.6 and @tooltip_msg != '' sender.text = @tooltip_msg.to_s sender.show else sender.hide end end |
#total_height(opts) ⇒ Object
1194 1195 1196 1197 1198 1199 1200 1201 |
# File 'lib/IFMapper/SVGMapExporter.rb', line 1194 def total_height(opts) total_height=0 @sections.each_with_index{ |sect, idx| maxy = sect.svg_height(opts) total_height = total_height + maxy } return total_height end |
#update_exits(selection) ⇒ Object
Find and update all paths in path map for a room
1595 1596 1597 1598 |
# File 'lib/IFMapper/FXMap.rb', line 1595 def update_exits(selection) create_pathmap @modified = true end |
#update_itemlist ⇒ Object
1588 1589 1590 |
# File 'lib/IFMapper/FXMap.rb', line 1588 def update_itemlist @@itemlist.copy_from(self) if @@itemlist end |
#update_roomlist ⇒ Object
If roomlist window is present, update it
1583 1584 1585 1586 |
# File 'lib/IFMapper/FXMap.rb', line 1583 def update_roomlist @@roomlist.copy_from(self) if @@roomlist @@win.copy_from(self) if @@win end |
#update_title ⇒ Object
Update the map window’s title
567 568 569 570 571 572 573 574 575 576 577 578 579 |
# File 'lib/IFMapper/FXMap.rb', line 567 def update_title title = @name.to_s.dup if title << " #{TITLE_READ_ONLY}" end if @automap title << " #{TITLE_AUTOMAP}" end title << " #{TITLE_ZOOM} %.3f" % @zoom title << " #{TITLE_SECTION} #{@section+1} #{TITLE_OF} #{@sections.size}" title << " #{@sections[@section].name}" @window.title = title end |
#zoom_in ⇒ Object
Self-explanatory.
815 816 817 818 819 |
# File 'lib/IFMapper/FXMap.rb', line 815 def zoom_in if @zoom < 1.25 self.zoom += 0.1 end end |
#zoom_out ⇒ Object
Self-explanatory.
808 809 810 811 812 |
# File 'lib/IFMapper/FXMap.rb', line 808 def zoom_out if @zoom > 0.1 self.zoom -= 0.1 end end |