File: gtk_message_picker.rb

package info (click to toggle)
mikutter 5.0.4%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,700 kB
  • sloc: ruby: 21,307; sh: 181; makefile: 19
file content (157 lines) | stat: -rw-r--r-- 5,016 bytes parent folder | download | duplicates (2)
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