#!/usr/bin/env ruby # wxRuby2 Sample Code. Copyright (c) 2004-2008 wxRuby development team # Adapted for wxRuby3 # Copyright (c) M.J.N. Corino, The Netherlands ### require 'wx' WXPRINT_QUIT = Wx::ID_EXIT WXPRINT_PRINT = Wx::ID_PRINT WXPRINT_PAGE_SETUP = Wx::ID_PRINT_SETUP WXPRINT_PREVIEW = Wx::ID_PREVIEW WXPRINT_PRINT_PS = 105 WXPRINT_PAGE_SETUP_PS = 107 WXPRINT_PREVIEW_PS = 108 WXPRINT_ABOUT = Wx::ID_ABOUT WXPRINT_ANGLEUP = 110 WXPRINT_ANGLEDOWN = 111 class MyFrame < Wx::Frame attr_accessor :canvas def initialize(parent, title, pos, size) super(parent, -1, title, pos, size) @canvas = nil @bitmap = Wx::Bitmap.new @angle = 30 # map events evt_menu(WXPRINT_QUIT) { |e| on_exit(e) } evt_menu(WXPRINT_PRINT) { |e| on_print(e) } evt_menu(WXPRINT_PREVIEW) { |e| on_print_preview(e) } evt_menu(WXPRINT_PAGE_SETUP) { |e| on_page_setup(e) } evt_menu(WXPRINT_ABOUT) { |e| on_print_about(e) } evt_menu(WXPRINT_ANGLEUP) { |e| on_angle_up(e) } evt_menu(WXPRINT_ANGLEDOWN) { |e| on_angle_down(e) } end def draw(dc) dc.set_background(Wx::WHITE_BRUSH) dc.clear() dc.set_font(Wx::get_app.test_font) dc.set_background_mode(Wx::BRUSHSTYLE_TRANSPARENT) dc.set_brush(Wx::CYAN_BRUSH) dc.set_pen(Wx::RED_PEN) dc.draw_rounded_rectangle(0, 20, 200, 80, 20) dc.draw_text("Rectangle 200 by 80", 40, 40) dc.set_pen(Wx::Pen.new(Wx::BLACK, 0, Wx::PENSTYLE_DOT_DASH)) dc.draw_ellipse(50, 140, 100, 50) dc.set_pen(Wx::RED_PEN) dc.draw_text("Test message: this is in 10 point text", 10, 180) test = "Hebrew שלום -- Japanese (日本語)" dc.draw_text(test, 10, 200) points = [] points << Wx::Point.new(0, 0) points << Wx::Point.new(20, 0) points << Wx::Point.new(20, 20) points << Wx::Point.new(10, 20) points << Wx::Point.new(10, -20) dc.draw_polygon(points, 20, 250, Wx::ODDEVEN_RULE) dc.draw_polygon(points, 50, 250, Wx::WINDING_RULE) dc.draw_elliptic_arc(80, 250, 60, 30, 0.0, 270.0) points[0].x = 150 points[0].y = 250 points[1].x = 180 points[1].y = 250 points[2].x = 180 points[2].y = 220 points[3].x = 200 points[3].y = 220 points.pop dc.draw_spline(points) dc.draw_arc(20, 10, 10, 10, 25, 40) str = "" i = 0 str = "---- Text at angle #{i} ----" dc.draw_rotated_text(str, 100, 300, i) i = @angle; str = "---- Text at angle #{i} ----" dc.draw_rotated_text(str, 100, 300, i) dc.set_pen(Wx::BLACK_PEN) dc.draw_line(0, 0, 200, 200) dc.draw_line(200, 0, 0, 200) # Load icon if Wx::PLATFORM == "WXMSW" icon_file = File.join(File.dirname(__FILE__), 'mondrian.ico') my_icon = Wx::Icon.new(icon_file, Wx::BITMAP_TYPE_ICO) else icon_file = File.join(File.dirname(__FILE__), 'mondrian.xpm') my_icon = Wx::Icon.new(icon_file, Wx::BITMAP_TYPE_XPM) end dc.draw_icon(my_icon, 100, 100) if @bitmap.is_ok dc.draw_bitmap(@bitmap, 10, 10) end end def on_angle_up(event) @angle += 5 canvas.refresh end def on_angle_down(event) @angle -= 5 canvas.refresh end def on_size(event) super(event) end def on_print(event) printer = Wx::Printer.new(Wx::PrintDialogData.new(Wx::get_app.page_setup_data.print_data)) printout = MyPrintout.new("My printout") if (!printer.print(self, printout, true)) if (Wx::Printer.get_last_error == Wx::PRINTER_ERROR) Wx::message_box("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", Wx::OK) else Wx::message_box("You canceled printing", "Printing", Wx::OK) end else Wx::get_app.page_setup_data.print_data = printer.print_dialog_data.print_data end end def on_print_preview(event) # Pass two printout objects: for preview, and possible printing. preview = Wx::PrintPreview.new(MyPrintout.new, MyPrintout.new, Wx::PrintDialogData.new(Wx::get_app.page_setup_data.print_data)) if not preview.is_ok # delete preview; Wx::message_box("There was a problem previewing.\nPerhaps your current printer is not set correctly?", "Previewing", Wx::OK) return end prev_frame = Wx::PreviewFrame.new(preview, self, "Demo Print Preview", Wx::Point.new(100, 100), Wx::Size.new(600, 650)) prev_frame.centre(Wx::BOTH) prev_frame.init prev_frame.show end def on_page_setup(event) Wx::PRT.PageSetupDialog(self, Wx::get_app.page_setup_data) do |dlg| dlg.show_modal Wx::get_app.page_setup_data = dlg.page_setup_data end end def on_exit(event) close(true) end def on_print_about(event) Wx::message_box("wxWidgets printing demo\nAuthor: Julian Smart\nAdapted to wxRuby by Sean Long", "About wxRuby printing demo", Wx::OK | Wx::CENTRE) end end class MyCanvas < Wx::ScrolledWindow # attr_accessor :frame def initialize(parent, pos, size, style = Wx::RETAINED) super(parent, -1, pos, size, style) @frame = parent set_background_colour(Wx::WHITE) evt_mouse_events() { |e| on_event(e) } end def on_draw(dc) @frame.draw(dc) end def on_event(event) end end class MyPrintout < Wx::Printout def initialize(title = "My printout") super(title) end def on_print_page(page) dc = get_dc if dc if page == 1 draw_page_one(dc) elsif (page == 2) draw_page_two(dc) end dc.set_device_origin(0, 0) dc.set_user_scale(1.0, 1.0) buf = "PAGE #{page}" dc.draw_text(buf, 10, 10) return true else return false end end def on_begin_document(start_page, end_page) go_ahead = super(start_page, end_page) if (!go_ahead) return false end return true end def has_page(page) return (page == 1 || page == 2) end def get_page_info min_page = 1 max_page = 2 sel_page_from = 1 sel_page_to = 2 [min_page, max_page, sel_page_from, sel_page_to] end def draw_page_one(dc) # You might use THIS code if you were scaling # graphics of known size to fit on the page. # We know the graphic is 200x200. If we didn't know this, # we'd need to calculate it. max_x = 200 max_y = 200 # Let's have at least 50 device units margin margin_x = 50 margin_y = 50 # Add the margin to the graphic size max_x += (2 * margin_x) max_y += (2 * margin_y) # Get the size of the DC in pixels size = dc.get_size w = size.get_width h = size.get_height # Calculate a suitable scaling factor scale_x = (w / max_x) scale_y = (h / max_y) # Use x or y scaling factor, whichever fits on the DC # actualScale = Wx::min(scaleX,scaleY) if scale_x < scale_y actual_scale = scale_x else actual_scale = scale_y end # Calculate the position on the DC for centring the graphic pos_x = ((w - (200 * actual_scale)) / 2.0) pos_y = ((h - (200 * actual_scale)) / 2.0) # Set the scale and origin dc.set_user_scale(actual_scale, actual_scale) dc.set_device_origin(pos_x.to_i, pos_y.to_i) Wx::get_app.frame.draw(dc) end def draw_page_two(dc) # You might use THIS code to set the printer DC to ROUGHLY reflect # the screen text size. This page also draws lines of actual length # 5cm on the page. # Get the logical pixels per inch of screen and printer ppi_screen_x, ppi_screen_y = get_ppi_screen ppi_printer_x, ppi_printer_y = get_ppi_printer # This scales the DC so that the printout roughly represents the # the screen scaling. The text point size _should_ be the right size # but in fact is too small for some reason. This is a detail that will # need to be addressed at some point but can be fudged for the # moment. scale = (ppi_printer_x.to_f / ppi_screen_x.to_f) # Now we have to check in case our real page size is reduced # (e.g. because we're drawing to a print preview memory DC) page_width, page_height = get_page_size_pixels size = dc.get_size w = size.get_width h = size.get_height # If printer pageWidth == current DC width, then this doesn't # change. But w might be the preview bitmap width, so scale down. overall_scale = scale * (w.to_f / page_width.to_f) dc.set_user_scale(overall_scale, overall_scale) # Calculate conversion factor for converting millimetres into # logical units. # There are approx. 25.4 mm to the inch. There are ppi # device units to the inch. Therefore 1 mm corresponds to # ppi/25.4 device units. We also divide by the # screen-to-printer scaling factor, because we need to # unscale to pass logical units to DrawLine. # Draw 50 mm by 50 mm L shape log_units_factor = (ppi_printer_x.to_f / (scale * 25.4)) log_units = (50 * log_units_factor) dc.set_pen(Wx::BLACK_PEN) dc.draw_line(50, 250, (50.0 + log_units).to_i, 250) dc.draw_line(50, 250, 50, (250.0 + log_units).to_i) dc.set_background_mode(Wx::BRUSHSTYLE_TRANSPARENT) dc.set_brush(Wx::TRANSPARENT_BRUSH) # GetTextExtent demo: words = ["This ", "is ", "GetTextExtent ", "testing ", "string. ", "Enjoy ", "it!"] w, h = 0, 0 x = 200 y = 250 fnt = Wx::Font.new(15, Wx::FONTFAMILY_SWISS, Wx::FONTSTYLE_NORMAL, Wx::FONTWEIGHT_NORMAL) dc.set_font(fnt) words.each do |word| w, h = dc.get_text_extent(word) dc.draw_rectangle(x, y, w.to_i, h.to_i) w, h = dc.get_text_extent(word) dc.draw_text(word, x, y) x += w end dc.set_font(Wx::get_app.test_font) dc.draw_text("Some test text", 200, 300) left_margin = 20 right_margin = 20 top_margin = 20 bottom_margin = 20 page_width_mm, page_height_mm = get_page_size_mm left_margin_logical = (log_units_factor * left_margin).to_i top_margin_logical = (log_units_factor * top_margin).to_i bottom_margin_logical = (log_units_factor * (page_height_mm - bottom_margin)).to_i right_margin_logical = (log_units_factor * (page_width_mm - right_margin)).to_i dc.set_pen(Wx::RED_PEN) dc.draw_line(left_margin_logical, top_margin_logical, right_margin_logical, top_margin_logical) dc.draw_line(left_margin_logical, bottom_margin_logical, right_margin_logical, bottom_margin_logical) write_page_header(self, dc, "A header", log_units_factor) end # Writes a header on a page. Margin units are in millimetres. def write_page_header(printout, dc, text, mm_to_logical) page_width_mm, page_height_mm = printout.get_page_size_mm left_margin = 10 top_margin = 10 right_margin = 10 left_margin_logical = (mm_to_logical * left_margin).to_i top_margin_logical = (mm_to_logical * top_margin).to_i right_margin_logical = (mm_to_logical * (page_width_mm - right_margin)).to_i x_extent, y_extent = dc.get_text_extent(text) x_pos = (((((page_width_mm - left_margin - right_margin) / 2.0) + left_margin) * mm_to_logical) - (x_extent / 2.0)) dc.draw_text(text, x_pos.to_i, top_margin_logical) dc.set_pen(Wx::BLACK_PEN) dc.draw_line(left_margin_logical, (top_margin_logical + y_extent).to_i, right_margin_logical, (top_margin_logical + y_extent).to_i) return true end end class MyApp < Wx::App attr_accessor :frame, :test_font, :page_setup_data def on_init @test_font = Wx::Font.new(10, Wx::FONTFAMILY_SWISS, Wx::FONTSTYLE_NORMAL, Wx::FONTWEIGHT_NORMAL) # Create the main frame window @frame = MyFrame.new(nil, "wxRuby Printing Demo", Wx::Point.new(0, 0), Wx::Size.new(400, 400)) # Give it a status line @frame.create_status_bar(2) # Load icon and bitmap if Wx::PLATFORM == "WXMSW" icon_file = File.join(File.dirname(__FILE__), 'mondrian.ico') @frame.set_icon(Wx::Icon.new(icon_file, Wx::BITMAP_TYPE_ICO)) else icon_file = File.join(File.dirname(__FILE__), 'mondrian.xpm') @frame.set_icon(Wx::Icon.new(icon_file, Wx::BITMAP_TYPE_XPM)) end # Make a menubar file_menu = Wx::Menu.new file_menu.append(WXPRINT_PRINT, "&Print...", "Print") file_menu.append(WXPRINT_PAGE_SETUP, "Page Set&up...", "Page setup") file_menu.append(WXPRINT_PREVIEW, "Print Pre&view", "Preview") =begin # Accelerators wxAcceleratorEntry entries[1]; entries[0].Set(wxACCEL_CTRL, (int) 'V', WXPRINT_PREVIEW); wxAcceleratorTable accel(1, entries); frame->SetAcceleratorTable(accel); =end file_menu.append_separator() file_menu.append(WXPRINT_ANGLEUP, "Angle up\tAlt-U", "Raise rotated text angle") file_menu.append(WXPRINT_ANGLEDOWN, "Angle down\tAlt-D", "Lower rotated text angle") file_menu.append_separator() file_menu.append(WXPRINT_QUIT, "E&xit", "Exit program") help_menu = Wx::Menu.new help_menu.append(WXPRINT_ABOUT, "&About", "About this demo") menu_bar = Wx::MenuBar.new menu_bar.append(file_menu, "&File") menu_bar.append(help_menu, "&Help") # Associate the menu bar with the frame @frame.set_menu_bar(menu_bar) canvas = MyCanvas.new(@frame, Wx::Point.new(0, 0), Wx::Size.new(100, 100), Wx::RETAINED | Wx::HSCROLL | Wx::VSCROLL) # Give it scrollbars: the virtual canvas is 20 * 50 = 1000 pixels in each direction canvas.set_scrollbars(20, 20, 50, 50) @frame.canvas = canvas @frame.centre(Wx::BOTH) @frame.show() @frame.set_status_text("Printing demo") set_top_window(@frame) #@print_data = Wx::PrintData.new @page_setup_data = Wx::PageSetupDialogData.new return true end def on_exit return true end end module PrintingSample include WxRuby::Sample if defined? WxRuby::Sample def self.describe { file: __FILE__, summary: 'wxRuby Printing example.', description: 'wxRuby example showcasing printing framework.' } end def self.run execute(__FILE__) end if $0 == __FILE__ MyApp.run end end