プロジェクト

全般

プロフィール

機能 #806 » 0001-SubPartsQuote.patch

Satoshi Okuno, 2016-01-03 14:31

差分を表示:

core/mui/cairo_sub_parts_message_base.rb
# -*- coding: utf-8 -*-
require 'gtk2'
require 'cairo'
# ナウい引用っぽくメッセージを作るサブパーツのベースクラス
# 継承して使おう
class Gdk::SubPartsMessageBase < Gdk::SubParts
attr_reader :icon_width, :icon_height
# サブクラスでMessagesを返すように実装すること
# このメソッドはサブパーツの描画中に何回も呼ばれるので、キャッシュなどで高速化に努めてください
def messages
nil end
# サブクラスで領域をクリックした時の処理を実装すること
def on_click(this, e, x, y, message)
end
def initialize(*args)
super
@icon_width, @icon_height, @margin, @edge = 32, 32, 2, 8 end
def render_messages
if not helper.destroyed?
helper.on_modify
helper.reset_height
helper.ssc(:click) { |this, e, x, y|
ofsty = helper.mainpart_height
helper.subparts.each { |part|
break if part == self
ofsty += part.height }
if ofsty <= y and (ofsty + height) >= y
my = 0
messages.each { |m|
my += message_height(m)
if y <= ofsty + my
on_click(e, m)
break end } end } end end
def render(context)
if messages and not messages.empty?
messages.inject(0) { |base_y, message|
render_single_message(message, context, base_y) } end end
def height
if not helper.destroyed? and messages and not messages.empty?
messages.inject(0) { |s, m| s + message_height(m) }
else
0 end end
private
def render_single_message(message, context, base_y)
render_outline(message, context, base_y)
render_header(message, context, base_y)
context.save {
context.translate(@margin + @edge, @margin + @edge + base_y)
context.set_source_pixbuf(main_icon(message))
context.paint
context.translate(icon_width + @margin*2, header_left(message).size[1] / Pango::SCALE)
context.set_source_rgb(*([0,0,0]).map{ |c| c.to_f / 65536 })
context.show_pango_layout(main_message(message, context)) }
base_y + message_height(message) end
def message_height(message)
[icon_height, (header_left(message).size[1] + main_message(message).size[1]) / Pango::SCALE].max + (@margin + @edge) * 2
end
# ヘッダ(左)のための Pango::Layout のインスタンスを返す
def header_left(message, context = dummy_context)
attr_list, text = Pango.parse_markup("<b>#{Pango.escape(message[:user][:idname])}</b> #{Pango.escape(message[:user][:name] || '')}")
layout = context.create_pango_layout
layout.attributes = attr_list
layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_basic_font])
layout.text = text
layout end
# ヘッダ(右)のための Pango::Layout のインスタンスを返す
def header_right(message, context = dummy_context)
now = Time.now
hms = if message[:created].year == now.year && message[:created].month == now.month && message[:created].day == now.day
message[:created].strftime('%H:%M:%S'.freeze)
else
message[:created].strftime('%Y/%m/%d %H:%M:%S'.freeze)
end
attr_list, text = Pango.parse_markup("<span foreground=\"#999999\">#{Pango.escape(hms)}</span>".freeze)
layout = context.create_pango_layout
layout.attributes = attr_list
layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_basic_font])
layout.text = text
layout.alignment = Pango::ALIGN_RIGHT
layout end
def render_header(message, context, base_y)
header_w = width - @icon_width - @margin*3 - @edge*2
context.save{
context.translate(@icon_width + @margin*2 + @edge, @margin + @edge + base_y)
context.set_source_rgb(0,0,0)
hl_layout, hr_layout = header_left(message, context), header_right(message, context)
context.show_pango_layout(hl_layout)
context.save{
context.translate(header_w - hr_layout.size[0] / Pango::SCALE, 0)
if (hl_layout.size[0] / Pango::SCALE) > header_w - hr_layout.size[0] / Pango::SCALE - 20
r, g, b = get_backgroundcolor
grad = Cairo::LinearPattern.new(-20, base_y, hr_layout.size[0] / Pango::SCALE + 20, base_y)
grad.add_color_stop_rgba(0.0, r, g, b, 0.0)
grad.add_color_stop_rgba(20.0 / (hr_layout.size[0] / Pango::SCALE + 20), r, g, b, 1.0)
grad.add_color_stop_rgba(1.0, r, g, b, 1.0)
context.rectangle(-20, base_y, hr_layout.size[0] / Pango::SCALE + 20, hr_layout.size[1] / Pango::SCALE + base_y)
context.set_source(grad)
context.fill() end
context.show_pango_layout(hr_layout) } }
end
def main_message(message, context = dummy_context)
attr_list, text = Pango.parse_markup(Pango.escape(message.to_show))
layout = context.create_pango_layout
layout.width = (width - @icon_width - @margin*3 - @edge*2) * Pango::SCALE
layout.attributes = attr_list
layout.wrap = Pango::WRAP_CHAR
layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_reply_font])
layout.text = text
layout end
def render_outline(message, context, base_y)
mh = message_height(message)
context.save {
context.pseudo_blur(4) {
context.fill {
context.set_source_rgb(*([32767, 32767, 32767]).map{ |c| c.to_f / 65536 })
context.rounded_rectangle(@edge, @edge + base_y, width - @edge*2, mh - @edge*2, 4)
}
}
context.fill {
context.set_source_rgb(*([65535, 65535, 65535]).map{ |c| c.to_f / 65536 })
context.rounded_rectangle(@edge, @edge + base_y, width - @edge*2, mh - @edge*2, 4)
}
}
end
def main_icon(message)
Gdk::WebImageLoader.pixbuf(message[:user][:profile_image_url], icon_width, icon_height){ |pixbuf|
helper.on_modify } end
def get_backgroundcolor
[1.0, 1.0, 1.0]
end
end
core/mui/cairo_sub_parts_quote.rb
# -*- coding: utf-8 -*-
miquire :mui, 'sub_parts_voter'
miquire :mui, 'sub_parts_message_base'
require 'gtk2'
require 'cairo'
class Gdk::SubPartsQuote < Gdk::SubParts
class Gdk::SubPartsQuote < Gdk::SubPartsMessageBase
register
attr_reader :icon_width, :icon_height
def messages
@messages end
def on_click(e, message)
case e.button
when 1
Plugin.filtering(:command, {}).first[:smartthread][:exec].call(Struct.new(:messages).new([message]))
end end
def initialize(*args)
super
@icon_width, @icon_height, @margin, @edge = 32, 32, 2, 8
if helper.message.quoting?
Thread.new(helper.message) { |m|
m.quoting_messages(true)
}.next{ |quoting|
@messages = Messages.new(quoting).freeze
render_messages
}.terminate('コメント付きリツイート描画中にエラーが発生しました') end end
def render_messages
if not helper.destroyed?
helper.on_modify
helper.reset_height
helper.ssc(:click) { |this, e, x, y|
ofsty = helper.mainpart_height
helper.subparts.each { |part|
break if part == self
ofsty += part.height }
if ofsty <= y and (ofsty + height) >= y
case e.button
when 1
my = 0
@messages.each { |m|
my += message_height(m)
if y <= ofsty + my
Plugin.filtering(:command, {}).first[:smartthread][:exec].call(Struct.new(:messages).new([m]))
break end } end end } end end
def render(context)
if @messages and not @messages.empty?
@messages.inject(0) { |base_y, message|
render_single_message(message, context, base_y) } end end
def height
if not helper.destroyed? and @messages and not @messages.empty?
@messages.inject(0) { |s, m| s + message_height(m) }
else
0 end end
private
def render_single_message(message, context, base_y)
render_outline(message, context, base_y)
render_header(message, context, base_y)
context.save {
context.translate(@margin + @edge, @margin + @edge + base_y)
context.set_source_pixbuf(main_icon(message))
context.paint
context.translate(icon_width + @margin*2, header_left(message).size[1] / Pango::SCALE)
context.set_source_rgb(*([0,0,0]).map{ |c| c.to_f / 65536 })
context.show_pango_layout(main_message(message, context)) }
base_y + message_height(message) end
def message_height(message)
[icon_height, (header_left(message).size[1] + main_message(message).size[1]) / Pango::SCALE].max + (@margin + @edge) * 2
end
# ヘッダ(左)のための Pango::Layout のインスタンスを返す
def header_left(message, context = dummy_context)
attr_list, text = Pango.parse_markup("<b>#{Pango.escape(message[:user][:idname])}</b> #{Pango.escape(message[:user][:name] || '')}")
layout = context.create_pango_layout
layout.attributes = attr_list
layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_basic_font])
layout.text = text
layout end
# ヘッダ(右)のための Pango::Layout のインスタンスを返す
def header_right(message, context = dummy_context)
now = Time.now
hms = if message[:created].year == now.year && message[:created].month == now.month && message[:created].day == now.day
message[:created].strftime('%H:%M:%S'.freeze)
else
message[:created].strftime('%Y/%m/%d %H:%M:%S'.freeze)
end
attr_list, text = Pango.parse_markup("<span foreground=\"#999999\">#{Pango.escape(hms)}</span>".freeze)
layout = context.create_pango_layout
layout.attributes = attr_list
layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_basic_font])
layout.text = text
layout.alignment = Pango::ALIGN_RIGHT
layout end
def render_header(message, context, base_y)
header_w = width - @icon_width - @margin*3 - @edge*2
context.save{
context.translate(@icon_width + @margin*2 + @edge, @margin + @edge + base_y)
context.set_source_rgb(0,0,0)
hl_layout, hr_layout = header_left(message, context), header_right(message, context)
context.show_pango_layout(hl_layout)
context.save{
context.translate(header_w - hr_layout.size[0] / Pango::SCALE, 0)
if (hl_layout.size[0] / Pango::SCALE) > header_w - hr_layout.size[0] / Pango::SCALE - 20
r, g, b = get_backgroundcolor
grad = Cairo::LinearPattern.new(-20, base_y, hr_layout.size[0] / Pango::SCALE + 20, base_y)
grad.add_color_stop_rgba(0.0, r, g, b, 0.0)
grad.add_color_stop_rgba(20.0 / (hr_layout.size[0] / Pango::SCALE + 20), r, g, b, 1.0)
grad.add_color_stop_rgba(1.0, r, g, b, 1.0)
context.rectangle(-20, base_y, hr_layout.size[0] / Pango::SCALE + 20, hr_layout.size[1] / Pango::SCALE + base_y)
context.set_source(grad)
context.fill() end
context.show_pango_layout(hr_layout) } }
end
def main_message(message, context = dummy_context)
attr_list, text = Pango.parse_markup(Pango.escape(message.to_show))
layout = context.create_pango_layout
layout.width = (width - @icon_width - @margin*3 - @edge*2) * Pango::SCALE
layout.attributes = attr_list
layout.wrap = Pango::WRAP_CHAR
layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_reply_font])
layout.text = text
layout end
def render_outline(message, context, base_y)
mh = message_height(message)
context.save {
context.pseudo_blur(4) {
context.fill {
context.set_source_rgb(*([32767, 32767, 32767]).map{ |c| c.to_f / 65536 })
context.rounded_rectangle(@edge, @edge + base_y, width - @edge*2, mh - @edge*2, 4)
}
}
context.fill {
context.set_source_rgb(*([65535, 65535, 65535]).map{ |c| c.to_f / 65536 })
context.rounded_rectangle(@edge, @edge + base_y, width - @edge*2, mh - @edge*2, 4)
}
}
end
def main_icon(message)
Gdk::WebImageLoader.pixbuf(message[:user][:profile_image_url], icon_width, icon_height){ |pixbuf|
helper.on_modify } end
def get_backgroundcolor
[1.0, 1.0, 1.0]
end
end
}.terminate('コメント付きリツイート描画中にエラーが発生しました') end end end
(1-1/2)