class Metasm::Gui::DrawableWidget
Constants
- BasicColor
- ColorTheme
- Keyboard_trad
keypress event keyval traduction table
Attributes
caret_x[RW]
caret_y[RW]
default_color_association[RW]
this hash is used to determine the colors of the Gui elements (background, caret, …) modifications to it are only useful before the widget is first rendered (IE before Metasm::Gui.main)
hl_word[RW]
hl_word_re[RW]
parent_widget[RW]
Public Class Methods
new(*a, &b)
click to toggle source
Calls superclass method
# File metasm/gui/gtk.rb, line 201 def initialize(*a, &b) @parent_widget = nil @caret_x = @caret_y = 0 # text cursor position @oldcaret_x = @oldcaret_y = 1 @hl_word = nil @layout = Pango::Layout.new Gdk::Pango.context # text rendering @color = {} @default_color_association = {:background => :palegrey} super() # events callbacks signal_connect('expose_event') { @w = window ; @gc = Gdk::GC.new(@w) protect { paint } @w = @gc = nil true } signal_connect('size_allocate') { |w, alloc| protect { resized(alloc.width, alloc.height) } } signal_connect('button_press_event') { |w, ev| @last_kb_ev = ev if keyboard_state(:control) next protect { click_ctrl(ev.x, ev.y) } if ev.event_type == Gdk::Event::Type::BUTTON_PRESS and ev.button == 1 and respond_to? :click_ctrl next end case ev.event_type when Gdk::Event::Type::BUTTON_PRESS grab_focus case ev.button when 1; protect { click(ev.x, ev.y) } if respond_to? :click end when Gdk::Event::Type::BUTTON2_PRESS case ev.button when 1; protect { doubleclick(ev.x, ev.y) } if respond_to? :doubleclick end end } signal_connect('motion_notify_event') { |w, ev| @last_kb_ev = ev if keyboard_state(:control) protect { mousemove_ctrl(ev.x, ev.y) } if respond_to? :mousemove_ctrl else protect { mousemove(ev.x, ev.y) } end } if respond_to? :mousemove signal_connect('button_release_event') { |w, ev| case ev.button when 1; protect { mouserelease(ev.x, ev.y) } if respond_to? :mouserelease when 3; protect { rightclick(ev.x, ev.y) } if respond_to? :rightclick end } signal_connect('scroll_event') { |w, ev| dir = case ev.direction when Gdk::EventScroll::Direction::UP; :up when Gdk::EventScroll::Direction::DOWN; :down else next end @last_kb_ev = ev if keyboard_state(:control) protect { mouse_wheel_ctrl(dir, ev.x, ev.y) } if respond_to? :mouse_wheel_ctrl else protect { mouse_wheel(dir, ev.x, ev.y) } end } if respond_to? :mouse_wheel signal_connect('key_press_event') { |w, ev| @last_kb_ev = ev key = Keyboard_trad[ev.keyval] if keyboard_state(:control) protect { keypress_ctrl(key) or (@parent_widget and @parent_widget.keypress_ctrl(key)) } else protect { keypress(key) or (@parent_widget and @parent_widget.keypress(key)) } end } signal_connect('realize') { BasicColor.each { |tag, val| @color[tag] = color(val) } set_color_association @default_color_association initialize_visible if respond_to? :initialize_visible } initialize_widget(*a, &b) # receive keyboard/mouse signals set_events Gdk::Event::ALL_EVENTS_MASK set_can_focus true set_font 'courier 10' end
Public Instance Methods
clipboard_copy(buf)
click to toggle source
# File metasm/gui/gtk.rb, line 508 def clipboard_copy(buf) clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY) clipboard.text = buf end
clipboard_paste()
click to toggle source
# File metasm/gui/gtk.rb, line 513 def clipboard_paste clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY) clipboard.wait_for_text end
color(val)
click to toggle source
create a color from a 'rgb' description
# File metasm/gui/gtk.rb, line 309 def color(val) if not @color[val] v = case val.length when 3; val.scan(/./).map { |c| (c*4).to_i(16) } when 6; val.scan(/../).map { |c| (c+c).to_i(16) } end @color[val] = Gdk::Color.new(*v) window.colormap.alloc_color(@color[val], true, true) end @color[val] end
draw_color(col)
click to toggle source
# File metasm/gui/gtk.rb, line 421 def draw_color(col) @gc.set_foreground color(col) end
draw_line(x, y, ex, ey)
click to toggle source
# File metasm/gui/gtk.rb, line 448 def draw_line(x, y, ex, ey) if x.abs > 0x7000 return if ex.abs > 0x7000 and ((ex < 0) == (x < 0)) ox = x x = ((x > 0) ? 0x7000 : -0x7000) y = ey+(x-ex)*(y-ey)/(ox-ex) end if ex.abs > 0x7000 oex = ex ex = ((ex > 0) ? 0x7000 : -0x7000) ey = y+(ex-x)*(ey-y)/(oex-x) end if y.abs > 0x7000 return if ey.abs > 0x7000 and ((ey < 0) == (y < 0)) oy = y y = ((y > 0) ? 0x7000 : -0x7000) x = ex+(y-ey)*(x-ex)/(oy-ey) end if ey.abs > 0x7000 oey = ey ey = ((ey > 0) ? 0x7000 : -0x7000) ex = x+(ey-y)*(ex-x)/(oey-y) end @w.draw_line(@gc, x, y, ex, ey) end
draw_line_color(col, x, y, ex, ey)
click to toggle source
# File metasm/gui/gtk.rb, line 475 def draw_line_color(col, x, y, ex, ey) draw_color(col) draw_line(x, y, ex, ey) end
draw_rectangle(x, y, w, h)
click to toggle source
# File metasm/gui/gtk.rb, line 425 def draw_rectangle(x, y, w, h) # GTK clips coords around 0x8000 return if x > 0x7000 or y > 0x7000 if x < -0x7000 w += x + 100 x = -100 end if y < -0x7000 h += y + 100 y = -100 end return if w <= 0 or h <= 0 w = 0x7000 if w > 0x7000 h = 0x7000 if h > 0x7000 @w.draw_rectangle(@gc, true, x, y, w, h) end
draw_rectangle_color(col, x, y, w, h)
click to toggle source
# File metasm/gui/gtk.rb, line 443 def draw_rectangle_color(col, x, y, w, h) draw_color(col) draw_rectangle(x, y, w, h) end
draw_string(x, y, str)
click to toggle source
# File metasm/gui/gtk.rb, line 480 def draw_string(x, y, str) return if x.abs > 0x7000 or y.abs > 0x7000 @layout.text = str @w.draw_layout(@gc, x, y, @layout) end
draw_string_color(col, x, y, str)
click to toggle source
# File metasm/gui/gtk.rb, line 486 def draw_string_color(col, x, y, str) draw_color(col) draw_string(x, y, str) end
draw_string_hl(col, x, y, str)
click to toggle source
same as #draw_string_color + hilight @hl_word_re
# File metasm/gui/gtk.rb, line 492 def draw_string_hl(col, x, y, str) if @hl_word while str =~ @hl_word_re s1, s2 = $1, $2 draw_string_color(col, x, y, s1) x += s1.length*@font_width hl_w = s2.length*@font_width draw_rectangle_color(:hl_word_bg, x, y, hl_w, @font_height) draw_string_color(:hl_word, x, y, s2) x += hl_w str = str[s1.length+s2.length..-1] end end draw_string_color(col, x, y, str) end
grab_focus()
click to toggle source
# File metasm/gui/qt.rb, line 276 def grab_focus; set_focus end
gui_update()
click to toggle source
# File metasm/gui/gtk.rb, line 417 def gui_update redraw end
height()
click to toggle source
# File metasm/gui/gtk.rb, line 403 def height allocation.height end
initialize_visible_()
click to toggle source
# File metasm/gui/win32.rb, line 1818 def initialize_visible_ BasicColor.each { |tag, val| @color[tag] = color(val) } @color[:winbg] = Win32Gui.getsyscolor(Win32Gui::COLOR_BTNFACE) set_color_association(@default_color_association) # should be called after Gui.main set_font('courier 10') initialize_visible if respond_to? :initialize_visible end
initialize_widget()
click to toggle source
# File metasm/gui/gtk.rb, line 304 def initialize_widget end
invalidate(x, y, w, h)
click to toggle source
# File metasm/gui/gtk.rb, line 394 def invalidate(x, y, w, h) return if not window window.invalidate Gdk::Rectangle.new(x, y, w, h), false end
invalidate_caret(cx, cy, x=0, y=0)
click to toggle source
# File metasm/gui/gtk.rb, line 390 def invalidate_caret(cx, cy, x=0, y=0) invalidate(x + cx*@font_width, y + cy*@font_height, 2, @font_height) end
keyPressEvent(key)
click to toggle source
# File metasm/gui/qt.rb, line 224 def keyPressEvent(key) val = key.key >= 128 ? Keyboard_trad[key.key] : key.text[0].ord # must use text[0] to differenciate downcase/upcase if key.modifiers.to_i & Qt::ControlModifier.to_i > 0 # AONETHUAAAAAAAAAAAAAAA protect { keypress_ctrl(val) } if respond_to? :keypress_ctrl else protect { keypress(val) } if respond_to? :keypress end end
keyboard_state(query=nil)
click to toggle source
# File metasm/gui/gtk.rb, line 518 def keyboard_state(query=nil) case query when :control, :ctrl ev = @last_kb_ev and ev.state & Gdk::Window::CONTROL_MASK == Gdk::Window::CONTROL_MASK when :shift ev = @last_kb_ev and ev.state & Gdk::Window::SHIFT_MASK == Gdk::Window::SHIFT_MASK when :alt ev = @last_kb_ev and ev.state & Gdk::Window::MOD1_MASK == Gdk::Window::MOD1_MASK else [:control, :shift, :alt].find_all { |s| keyboard_state(s) } end end
keypress(key)
click to toggle source
# File metasm/gui/gtk.rb, line 411 def keypress(key) end
keypress_(key)
click to toggle source
# File metasm/gui/win32.rb, line 1868 def keypress_(key) # XXX my gtk api sux if not respond_to? :keypress or not protect { keypress(key) } protect { @parent.keypress(key) } if @parent.respond_to? :keypress end end
keypress_ctrl(key)
click to toggle source
# File metasm/gui/gtk.rb, line 414 def keypress_ctrl(key) end
keypress_ctrl_(key)
click to toggle source
# File metasm/gui/win32.rb, line 1875 def keypress_ctrl_(key) if not respond_to? :keypress_ctrl or not protect { keypress_ctrl(key) } protect { @parent.keypress_ctrl(key) } if @parent.respond_to? :keypress_ctrl end end
mouseDoubleClickEvent(ev)
click to toggle source
# File metasm/gui/qt.rb, line 245 def mouseDoubleClickEvent(ev) protect { doubleclick(ev.x, ev.y) } if respond_to? :doubleclick end
mouseMoveEvent(ev)
click to toggle source
# File metasm/gui/qt.rb, line 255 def mouseMoveEvent(ev) if ev.modifiers.to_i & Qt::ControlModifier.to_i > 0 protect { mousemove_ctrl(ev.x, ev.y) } if respond_to? :mousemove_ctrl else protect { mousemove(ev.x, ev.y) } if respond_to? :mousemove end end
mousePressEvent(ev)
click to toggle source
# File metasm/gui/qt.rb, line 233 def mousePressEvent(ev) if ev.modifiers.to_i & Qt::ControlModifier.to_i > 0 protect { click_ctrl(ev.x, ev.y) } if respond_to? :click_ctrl else if ev.button == Qt::LeftButton protect { click(ev.x, ev.y) } elsif ev.button == Qt::RightButton protect { rightclick(ev.x, ev.y) } if respond_to? :rightclick end end end
mouseReleaseEvent(ev)
click to toggle source
# File metasm/gui/qt.rb, line 249 def mouseReleaseEvent(ev) if ev.button == Qt::LeftButton protect { mouserelease(ev.x, ev.y) } if respond_to? :mouserelease end end
paint()
click to toggle source
# File metasm/gui/gtk.rb, line 382 def paint end
paintEvent(*a)
click to toggle source
# File metasm/gui/qt.rb, line 278 def paintEvent(*a) @painter = Qt::Painter.new(self) protect { paint } @painter.end @painter = nil end
paint_(realhdc)
click to toggle source
# File metasm/gui/win32.rb, line 1846 def paint_(realhdc) @hdc = Win32Gui.createcompatibledc(realhdc) bmp = Win32Gui.createcompatiblebitmap(realhdc, @width, @height) Win32Gui.selectobject(@hdc, bmp) Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::DC_BRUSH)) Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::DC_PEN)) Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::ANSI_FIXED_FONT)) Win32Gui.setbkmode(@hdc, Win32Gui::TRANSPARENT) draw_rectangle_color(:background, 0, 0, @width, @height) paint Win32Gui.bitblt(realhdc, @x, @y, @width, @height, @hdc, 0, 0, Win32Gui::SRCCOPY) Win32Gui.deleteobject(bmp) Win32Gui.deletedc(@hdc) @hdc = nil end
redraw()
click to toggle source
invalidate the whole widget area
# File metasm/gui/gtk.rb, line 386 def redraw invalidate(0, 0, 1000000, 1000000) end
resizeEvent(ev)
click to toggle source
# File metasm/gui/qt.rb, line 272 def resizeEvent(ev) protect { resized(ev.size.width, ev.size.height) } if respond_to? :resized end
resized(w, h)
click to toggle source
# File metasm/gui/gtk.rb, line 407 def resized(w, h) redraw end
resized_(w, h)
click to toggle source
# File metasm/gui/win32.rb, line 1862 def resized_(w, h) @width = w @height = h resized(w, h) if respond_to? :resized end
set_caret_from_click(x, y)
click to toggle source
# File metasm/gui/gtk.rb, line 321 def set_caret_from_click(x, y) @caret_x = (x-1).to_i / @font_width @caret_y = y.to_i / @font_height update_caret end
set_color_association(hash)
click to toggle source
change the color association arg is a hash function symbol => color symbol check initialize/sig('realize') for initial function/color list if called before the widget is first displayed onscreen, will register a hook to re-call itself later
# File metasm/gui/gtk.rb, line 340 def set_color_association(hash) if not realized? sid = signal_connect('realize') { signal_handler_disconnect(sid) set_color_association(hash) } else hord = Hash.new { |h, k| h[k] = (hash[k] ? h[hash[k]] + 1 : 0) } hash.sort_by { |k, v| hord[k] }.each { |k, v| @color[k] = color(v) } modify_bg Gtk::STATE_NORMAL, @color[:background] gui_update end end
set_font(descr)
click to toggle source
change the font of the widget arg is a Gtk Fontdescription string (eg 'courier 10')
# File metasm/gui/gtk.rb, line 329 def set_font(descr) @layout.font_description = Pango::FontDescription.new(descr) @layout.text = 'x' @font_width, @font_height = @layout.pixel_size gui_update end
update_hl_word(line, offset, mode=:asm)
click to toggle source
update @hl_word from a line & offset, return nil if unchanged
# File metasm/gui/gtk.rb, line 365 def update_hl_word(line, offset, mode=:asm) return if not line word = line[0...offset].to_s[/\w*$/] << line[offset..-1].to_s[/^\w*/] word = nil if word == '' if @hl_word != word if word if mode == :asm and defined?(@dasm) and @dasm re = @dasm.gui_hilight_word_regexp(word) else re = Regexp.escape word end @hl_word_re = /^(.*?)(\b(?:#{re})\b)/ end @hl_word = word end end
wheelEvent(ev)
click to toggle source
# File metasm/gui/qt.rb, line 263 def wheelEvent(ev) dir = ev.delta > 0 ? :up : :down if ev.modifiers.to_i & Qt::ControlModifier.to_i > 0 protect { mouse_wheel_ctrl(dir, ev.x, ev.y) } if respond_to? :mouse_wheel_ctrl else protect { mouse_wheel(dir, ev.x, ev.y) } if respond_to? :mouse_wheel end end
width()
click to toggle source
# File metasm/gui/gtk.rb, line 399 def width allocation.width end