1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
# -*- coding: utf-8 -*-
require 'mui/cairo_miracle_painter'
require 'gtk3'
module Gtk
class CellRendererMessage < CellRendererPixbuf
type_register
install_property(GLib::Param::String.new("uri", "uri", "Resource URI", "hoge", GLib::Param::READABLE|GLib::Param::WRITABLE))
attr_reader :message
def initialize()
super() end
# Register events for this Renderer:
signal_new("button_press_event", GLib::Signal::RUN_FIRST, nil, nil,
Gdk::EventButton, Gtk::TreePath, Gtk::TreeViewColumn,
Integer, Integer)
signal_new("button_release_event", GLib::Signal::RUN_FIRST, nil, nil,
Gdk::EventButton, Gtk::TreePath, Gtk::TreeViewColumn,
Integer, Integer)
signal_new("motion_notify_event", GLib::Signal::RUN_FIRST, nil, nil,
Gdk::EventMotion,
Gtk::TreePath, Gtk::TreeViewColumn,
Integer, Integer)
signal_new("leave_notify_event", GLib::Signal::RUN_FIRST, nil, nil,
Gdk::EventCrossing, Gtk::TreePath, Gtk::TreeViewColumn, Integer, Integer)
signal_new("click", GLib::Signal::RUN_FIRST, nil, nil,
Gdk::EventButton, Gtk::TreePath, Gtk::TreeViewColumn,
Integer, Integer)
def signal_do_button_press_event(e, path, column, cell_x, cell_y)
end
def signal_do_button_release_event(e, path, column, cell_x, cell_y)
end
def signal_do_motion_notify_event(e, path, column, cell_x, cell_y)
end
def signal_do_leave_notify_event(e, path, column, cell_x, cell_y)
end
def signal_do_click(e, path, column, cell_x, cell_y)
end
def tree=(tree)
@tree = tree
tree.add_events(Gdk::Event::BUTTON_PRESS_MASK|Gdk::Event::BUTTON_RELEASE_MASK)
armed_column = nil
last_motioned = nil
click_start = []
tree.ssc("leave_notify_event") { |w, e|
if last_motioned
signal_emit("leave_notify_event", e, *last_motioned)
last_motioned = nil end
false }
tree.ssc("motion_notify_event") { |w, e|
path, column, cell_x, cell_y = tree.get_path_at_pos(e.x, e.y)
if column
armed_column = column
motioned = [path, column, cell_x, cell_y]
signal_emit("motion_notify_event", e, *motioned)
if last_motioned
motioned_message = @tree.get_record(motioned[0]).message rescue nil
last_motioned_message = @tree.get_record(last_motioned[0]).message rescue nil
if(last_motioned_message and motioned_message != last_motioned_message)
emit_leave_notify_from_event_motion(e, *last_motioned) end end
last_motioned = motioned end }
tree.ssc("button_press_event") { |w, e|
path, column, cell_x, cell_y = tree.get_path_at_pos(e.x, e.y)
click_start = [cell_x, cell_y]
if column
armed_column = column
signal_emit("button_press_event", e, path, column, cell_x, cell_y) end
e.button == 3 && tree.get_active_pathes.include?(path) # 選択してるものを右クリックした時は、他のセルの選択を解除しない
}
tree.ssc("button_release_event") { |w, e|
path, column, cell_x, cell_y = tree.get_path_at_pos(e.x, e.y)
if column
cell_x ||= -1
cell_y ||= -1
signal_emit("button_release_event", e, path, column, cell_x, cell_y)
if click_start.size == 2 and click_start.all?{|x| x.respond_to? :-} and (column == armed_column) and (click_start[0] - cell_x).abs <= 4 and (click_start[1] - cell_y).abs <= 4
signal_emit("click", e, path, column, cell_x, cell_y) end
armed_column = nil end }
last_selected = Set.new(tree.selection.to_enum(:selected_each).map{ |m, p, i| i[3] }).freeze
tree.selection.ssc("changed") { |this|
now_selecting = Set.new(this.to_enum(:selected_each).map{ |m, p, i| i[3] }).freeze
new_selected = now_selecting - last_selected
unselected = last_selected - now_selecting
new_selected.each(&:on_selected)
unselected.each(&:on_unselected)
last_selected = now_selecting
false }
event_hooks end
# Messageに関連付けられた Gdk::MiraclePainter を取得する
def miracle_painter(message)
record = @tree.get_record_by_message(message)
if record and record.miracle_painter
record.miracle_painter
else
@tree.update!(message, Gtk::TimeLine::InnerTL::MIRACLE_PAINTER, create_miracle_painter(message)) end end
# MiraclePainterを生成して返す
def create_miracle_painter(message)
Gdk::MiraclePainter.new(message, avail_width).set_tree(@tree)
end
def uri=(uri)
record = @tree.get_record_by_uri(uri)
if record and record.message
return render_message(record.message)
else
self.pixbuf = Skin[:notfound].pixbuf(width: 64, height: 64) end
rescue Exception => err
error "#{err.class}: \"#{err.message}\" by uri: #{uri} model: #{record&.message&.inspect}"
# for ruby >= 2.5
error "#{err.full_message}" if err.respond_to?(:full_message)
raise if Mopt.debug
error err
self.pixbuf = Skin[:notfound].pixbuf(width: 64, height: 64) end
private
def user
message[:user]
end
def render_message(message)
if(@tree.realized?)
h = miracle_painter(message).height
miracle_painter(message).width = @tree.get_cell_area(nil, @tree.get_column(0)).width
if(h != miracle_painter(message).height)
@tree.get_column(0).queue_resize end end
self.pixbuf = miracle_painter(message).pixbuf end
# 描画するセルの横幅を取得する
def avail_width
[@tree.get_column(0).width, 100].max
end
def event_hooks
last_pressed = nil
ssc(:click, @tree){ |r, e, path, column, cell_x, cell_y|
record = @tree.get_record(path)
record.miracle_painter.clicked(cell_x, cell_y, e) if record
false }
ssc(:button_press_event, @tree){ |r, e, path, column, cell_x, cell_y|
record = @tree.get_record(path)
if record
last_pressed = record.miracle_painter
if e.button == 1
last_pressed.pressed(cell_x, cell_y) end
Delayer.new(:ui_response) {
Plugin::GUI.keypress(::Gtk::buttonname([e.event_type, e.button, e.state]), @tree.imaginary) }
end
false }
ssc(:button_release_event, @tree){ |r, e, path, column, cell_x, cell_y|
if e.button == 1 and last_pressed
record = @tree.get_record(path)
if record
if(last_pressed == record.miracle_painter)
last_pressed.released(cell_x, cell_y)
else
last_pressed.released end end
last_pressed = nil end
false }
ssc(:motion_notify_event, @tree){ |r, ev, path, column, cell_x, cell_y|
record = @tree.get_record(path)
record.miracle_painter.point_moved(ev, cell_x, cell_y) if record
false }
ssc(:leave_notify_event, @tree){ |r, ev, path, column, cell_x, cell_y|
record = @tree.get_record(path)
record.miracle_painter.point_leaved(ev, cell_x, cell_y) if record
false }
end
def emit_leave_notify_from_event_motion(e, *args)
# signal_emit("leave_notify_event",
# Gdk::EventCrossing.new(Gdk::Event::LEAVE_NOTIFY).tap{ |le|
# le.time = e.time
# le.x, le.y = e.x, e.y
# le.x_root, le.y_root = e.x_root, e.y_root
# le.focus = true
# }, *args) end
end
end
end
|