File: interactive.rb

package info (click to toggle)
mikutter 4.1.3%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 9,260 kB
  • sloc: ruby: 20,126; sh: 183; makefile: 19
file content (131 lines) | stat: -rw-r--r-- 4,480 bytes parent folder | download
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
# -*- coding: utf-8 -*-

module Plugin::Guide
  module InteractiveMixin
    def say(message)
      self.next {
        Plugin[:guide].timeline(:guide) <<
          Mikutter::System::Message.new(description: message,
                                        source: "guide",
                                        created: Time.now)
      }.extend(InteractiveMixin)
    end

    def prompt(message, choose = {Plugin[:change_account]._('次へ') => nil})
      self.next {
        promise = Deferred.new(true).extend(InteractiveMixin)
        Plugin[:guide].timeline(:guide) <<
          Mikutter::System::Message.new(description: message,
                                        source: "guide",
                                        created: Time.now,
                                        confirm: choose,
                                        confirm_callback: promise)
        promise
      }
    end

    def next(&block)
      super(&block).extend(InteractiveMixin) end

    def trap(&block)
      super(&block).extend(InteractiveMixin) end

  end

  class Interactive < Deferred
    include InteractiveMixin

    def self.generate
      Deferred.new.extend(InteractiveMixin)
    end
  end

  class SubPartsGuide < Gdk::SubParts
    Button = Struct.new(:layout, :value, :x, :y, :width, :height)
    OutsideOffset = 48          # 最初のボタンの左端との隙間
    ButtonLeft = 6              # ボタンの左端と文字の左側の距離
    ButtonRight = 6             # ボタンの右端と文字の右側の距離
    ButtonTop = 6               # わかるよね
    ButtonBottom = 6            # わかるよね
    ButtonMargin = 3            # ボタンとボタンの距離

    register

    def initialize(*args)
      super
      if message[:confirm]
        sid = 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 and 1 == e.button
            button = generate_buttons.find{|b| b.x < x and x < (b.x+b.width) }
            if button
              helper.signal_handler_disconnect(sid)
              message[:confirm] = nil
              helper.reset_height
              message[:confirm_callback].call(button.value) end end
          false } end
    end

    def render(context)
      if helper.visible? and message and message[:confirm]
        context.save{
          buttons = generate_buttons(context)
          return if not buttons
          buttons.each{ |button|
            render_outline(context, button.x, button.y, *button.layout.size.map{|_|_/Pango::SCALE})
            context.save{
              context.translate(button.x + ButtonLeft, button.y + ButtonTop)
              context.set_source_rgb(*(UserConfig[:mumble_basic_color] || [0,0,0]).map{ |c| c.to_f / 65536 })
              context.show_pango_layout(button.layout) } } } end end

    def height
      buttons = generate_buttons
      return 0 if not buttons
      @height ||= (buttons.map{|b|b.layout.size[1]}.max / Pango::SCALE) + ButtonMargin*2 + ButtonTop + ButtonBottom end

    private

    def generate_buttons(context = Cairo::Context.dummy)
      if not message[:confirm]
        return nil end
      ofst = OutsideOffset + ButtonMargin
      message[:confirm].map{ |label, value|
        layout = context.create_pango_layout
        layout.font_description = helper.font_description(UserConfig[:mumble_basic_font])
        layout.text = label
        width = layout.size[0]/Pango::SCALE + ButtonLeft + ButtonRight
        x = ofst
        ofst += width + ButtonMargin
        Button.new(layout, value,
                   x, 0,
                   width,
                   layout.size[1]/Pango::SCALE + ButtonTop + ButtonBottom) } end

    def render_outline(context, x, y, width, height)
      rect = [ButtonMargin + x,
              ButtonMargin + y,
              width - ButtonMargin*2 + ButtonLeft + ButtonRight,
              height - ButtonMargin*2 + ButtonTop + ButtonBottom, 4]
      context.save {
        context.pseudo_blur(4) {
          context.fill {
            context.set_source_rgb(0.5, 0.5, 0.5)
            context.rounded_rectangle(*rect)
          }
        }
        context.fill {
          context.set_source_rgb(1, 0.95, 0.95)
          context.rounded_rectangle(*rect)
        }
      }
    end

    def message
      helper.message end

  end

end