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
|
# frozen_string_literal: true
UserConfig[:profile_icon_size] ||= 48
UserConfig[:profile_icon_margin] ||= 4
Plugin.create :modelviewer do
defdsl :defmodelviewer do |model_class, &block|
model_class = Diva::Model(model_class) unless model_class.is_a?(Class)
filter_modelviewer_models do |models|
models << model_class.spec
[models]
end
intent(
model_class,
label: _('%{model}の詳細') % { model: model_class.spec&.name || model_class.name },
slug: :"modelviewer:#{model_class.slug}"
) do |token|
model = token.model
tab_slug = :"modelviewer:#{model_class.slug}:#{model.uri.hash}"
cluster_slug = :"modelviewer-cluster:#{model_class.slug}:#{model.uri.hash}"
if Plugin::GUI::Tab.exist?(tab_slug)
Plugin::GUI::Tab.instance(tab_slug).active!
else
tab(tab_slug, _('%{title}について') % { title: model.title }) do
set_icon model.icon if model.respond_to?(:icon)
set_deletable true
temporary_tab true
shrink
nativewidget Plugin[:modelviewer].header(token, &block)
expand
Plugin[:modelviewer].cluster_initialize(model, cluster(cluster_slug))
active!
end
end
end
end
# プロフィールタブを定義する
# ==== Args
# [slug] タブスラッグ
# [title] タブのタイトル
defdsl :deffragment do |model_class, slug, title=slug.to_s, &block|
model_class = Diva::Model(model_class) unless model_class.is_a?(Class)
add_event_filter(:"modelviewer_#{model_class.slug}_fragments") do |tabs, model|
i_fragment = Plugin::GUI::Fragment.instance(:"modelviewer-fragment:#{slug}:#{model.uri}", title)
i_fragment.instance_eval_with_delegate(self, model, &block)
tabs << i_fragment
[tabs, model]
end
end
on_gui_child_reordered do |i_cluster, i_fragment, _|
kind, = i_fragment.slug.to_s.split(':', 2)
if kind == 'modelviewer-fragment'
_, cluster_kind, = i_cluster.slug.to_s.split(':', 3)
store("order-#{cluster_kind}", i_cluster.children.map { |f| f.slug.to_s.split(':', 3)[1] })
end
end
def cluster_initialize(model, i_cluster)
_, cluster_kind, = i_cluster.slug.to_s.split(':', 3)
order = at("order-#{cluster_kind}", [])
fragments = Plugin.collect(:"modelviewer_#{model.class.slug}_fragments", Pluggaloid::COLLECT, model).sort_by { |i_fragment|
_, fragment_kind, = i_fragment.slug.to_s.split(':', 3)
order.index(fragment_kind) || Float::INFINITY
}.to_a
fragments.each(&i_cluster.method(:add_child))
fragments.first&.active!
end
def header(intent_token, &column_generator)
model = intent_token.model
icon = model_icon model
icon.margin = UserConfig[:profile_icon_margin]
icon.valign = :start
title = title_widget model
title.hexpand = true
table = header_table(model, column_generator.(model))
table.hexpand = true
grid = Gtk::Grid.new
grid.margin_top = grid.margin_bottom = 4
grid.attach_next_to icon, nil, :left, 1, 2
grid.attach_next_to title, icon, :right, 1, 1
grid.attach_next_to table, title, :bottom, 1, 1
grid
end
def model_icon(model)
return ::Gtk::EventBox.new unless model.respond_to?(:icon)
icon = ::Gtk::EventBox.new.add(::Gtk::WebIcon.new(model.icon, UserConfig[:profile_icon_size], UserConfig[:profile_icon_size]).set_tooltip_text(_('アイコンを開く')))
icon.ssc(:button_press_event) do
Plugin.call(:open, model.icon)
true
end
icon.ssc(:realize) do |this|
this.window.set_cursor(Gdk::Cursor.new(:hand2))
false
end
icon
end
# modelのtitleを表示する
# ==== Args
# [model] 表示するmodel
# [intent_token] ユーザを開くときに利用するIntent
# ==== Return
# ユーザの名前の部分のGtkコンテナ
def title_widget(model)
score = [
Plugin::Score::HyperLinkNote.new(
description: model.title,
uri: model.uri
)
]
::Gtk::IntelligentTextview.new(score)
end
# modelのtitleを表示する
# ==== Args
# [model] 表示するmodel
# [intent_token] ユーザを開くときに利用するIntent
# ==== Return
# ユーザの名前の部分のGtkコンテナ
def cell_widget(model_or_str)
case model_or_str
when Diva::Model
::Gtk::IntelligentTextview.new(
Plugin[:modelviewer].score_of(model_or_str),
)
else
Gtk::Label.new model_or_str.to_s
end
end
def header_table(model, rows)
grid = Gtk::Grid.new
grid.row_spacing = 4
grid.column_spacing = 16
rows.each do |header, content|
label_header = Gtk::Label.new header
label_header.halign = :end
widget_content = cell_widget content
widget_content.halign = :start
grid.attach_next_to label_header, nil, :bottom, 1, 1
grid.attach_next_to widget_content, label_header, :right, 1, 1
end
grid
end
end
|