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
|
# -*- coding: utf-8 -*-
require 'gtk3'
require 'miku/miku'
require 'mui/gtk_extension'
require 'mui/gtk_mtk'
require 'mui/gtk_webicon'
require 'skin'
class Gtk::MessagePicker < Gtk::Frame
DEFAULT_CONDITION = [:==, :user, ''.freeze].freeze
def initialize(conditions, &block)
conditions = [] unless conditions.is_a? MIKU::List
super()
@not = (conditions.respond_to?(:car) and (conditions.car == :not))
if(@not)
conditions = (conditions[1] or []).freeze end
@changed_hook = block
@function, *exprs = *conditions
@function ||= :and
self.border_width = 8
self.label_widget = option_widgets
shell = Gtk::Grid.new
shell.orientation = :vertical
@container = Gtk::Grid.new
@container.orientation = :vertical
@container.expand = true
buttons = add_button
buttons.halign = :center
add(shell.add(@container).add(buttons))
exprs.each{|x| add_condition(x) }
end
def function(new = @function)
(new ? :or : :and) end
def option_widgets
@option_widgets ||= Gtk::Grid.new.
add(Mtk::boolean(lambda{ |new|
unless new.nil?
@function = function(new)
call end
@function == :or },
'いずれかにマッチする')).
add(Mtk::boolean(lambda{ |new|
unless new.nil?
@not = new
call end
@not },
'否定')) end
def add_button
@add_button ||= gen_add_button end
def add_condition(expr = DEFAULT_CONDITION)
pack = Gtk::Grid.new
close = Gtk::Button.new.add(Gtk::WebIcon.new(Skin[:close], 16, 16)).set_relief(Gtk::RELIEF_NONE)
close.valign = :start
close.signal_connect(:clicked){
@container.remove(pack)
pack.destroy
call
false }
pack.add(close)
case expr.first
when :and, :or, :not
pack.add(Gtk::MessagePicker.new(expr, &method(:call)))
else
pack.add(Gtk::MessagePicker::PickCondition.new(expr, &method(:call))) end
@container.add(pack) end
def to_a
result = [
@function,
*@container.children.map do |c| # c: Gtk::Grid
c.children.select do |w| # w: Gtk::Widget
(w.is_a?(Gtk::MessagePicker) ||
w.is_a?(Gtk::MessagePicker::PickCondition))
end.first.to_a
end.reject(&:empty?)
].freeze
if result.size == 1
[].freeze
else
if @not
result = [:not, result].freeze end
result end end
private
def call
if @changed_hook
@changed_hook.call end end
def gen_add_button
container = Gtk::Grid.new
btn = Gtk::Button.new(label: '条件を追加')
btn.signal_connect(:clicked){
add_condition.show_all }
btn2 = Gtk::Button.new(label: 'サブフィルタを追加')
btn2.signal_connect(:clicked){
add_condition([:and, DEFAULT_CONDITION]).show_all }
container.add(btn).add(btn2) end
class PickCondition < Gtk::Grid
def initialize(conditions = DEFAULT_CONDITION, &block)
super()
@changed_hook = block
@condition, @subject, @expr = *conditions
build
end
def to_a
[@condition, @subject, @expr].freeze end
private
def call
if @changed_hook
@changed_hook.call end end
def build
extract_condition = Plugin.filtering(:extract_condition, []).first.to_h { |ec| [ec.slug, ec] }
w_argument = Mtk::input(lambda{ |new|
unless new === nil
@expr = new.freeze
call end
@expr },
nil)
w_operator = Mtk::chooseone(lambda{ |new|
unless new === nil
@condition = new.to_sym
call end
@condition.to_s },
nil,
Plugin.filtering(:extract_operator, []).first.to_h { |eo| [eo.slug.to_s, eo.name] })
w_condition = Mtk::chooseone(lambda{ |new|
unless new === nil
@subject = new.to_sym
call end
sensitivity = extract_condition.dig(@subject, :operator) && 0 != extract_condition.dig(@subject, :args)
w_argument.set_sensitive(sensitivity)
w_operator.set_sensitive(sensitivity)
@subject.to_s },
nil,
extract_condition.to_h { |slug, ec| [slug.to_s, ec.name] })
add(w_condition)
add(w_operator)
add(w_argument)
end
end
end
|