Class: Shoes::App

Inherits:
Object show all
Includes:
Mod2
Defined in:
lib/shoes/app.rb,
lib/shoes/text.rb,
lib/shoes/style.rb,
lib/plugins/video.rb,
lib/shoes/helper_methods.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Mod2

#init_app_vars

Constructor Details

#initialize(args = {}) ⇒ App

Returns a new instance of App.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/shoes/app.rb', line 5

def initialize args={}
  args.each do |k, v|
    instance_variable_set "@#{k}", v
  end

  win_title = @owner.instance_variable_get('@title')
  class << @owner; self end.
  class_eval do
    define_method :inspect do
      win_title or 'purple shoes'
    end
  end if @owner

  App.class_eval do
    attr_accessor *(args.keys - [:width, :height, :title])
  end
  init_app_vars
  @top_slot, @cslot = nil, self
  Shoes.APPS << self
end

Instance Attribute Details

#contentsObject

Returns the value of attribute contents.



26
27
28
# File 'lib/shoes/app.rb', line 26

def contents
  @contents
end

#cslotObject

Returns the value of attribute cslot.



26
27
28
# File 'lib/shoes/app.rb', line 26

def cslot
  @cslot
end

#focus_eleObject

Returns the value of attribute focus_ele.



26
27
28
# File 'lib/shoes/app.rb', line 26

def focus_ele
  @focus_ele
end

#hidedObject

Returns the value of attribute hided.



26
27
28
# File 'lib/shoes/app.rb', line 26

def hided
  @hided
end

#locationObject (readonly)

Returns the value of attribute location.



28
29
30
# File 'lib/shoes/app.rb', line 28

def location
  @location
end

#mhcsObject

Returns the value of attribute mhcs.



26
27
28
# File 'lib/shoes/app.rb', line 26

def mhcs
  @mhcs
end

#mmcsObject

Returns the value of attribute mmcs.



26
27
28
# File 'lib/shoes/app.rb', line 26

def mmcs
  @mmcs
end

#mouse_button=(value) ⇒ Object (writeonly)

Sets the attribute mouse_button

Parameters:

  • value

    the value to set the attribute mouse_button to.



27
28
29
# File 'lib/shoes/app.rb', line 27

def mouse_button=(value)
  @mouse_button = value
end

#mouse_posObject

Returns the value of attribute mouse_pos.



26
27
28
# File 'lib/shoes/app.rb', line 26

def mouse_pos
  @mouse_pos
end

#mscsObject

Returns the value of attribute mscs.



26
27
28
# File 'lib/shoes/app.rb', line 26

def mscs
  @mscs
end

#orderObject

Returns the value of attribute order.



26
27
28
# File 'lib/shoes/app.rb', line 26

def order
  @order
end

#ownerObject (readonly)

Returns the value of attribute owner.



28
29
30
# File 'lib/shoes/app.rb', line 28

def owner
  @owner
end

#top_slotObject

Returns the value of attribute top_slot.



26
27
28
# File 'lib/shoes/app.rb', line 26

def top_slot
  @top_slot
end

Instance Method Details

#aflushObject



817
818
819
820
821
822
823
824
# File 'lib/shoes/app.rb', line 817

def aflush
  @hided = true
  Swt::Display.getDefault.asyncExec do
    Shoes.call_back_procs self
    @hided = false
    @cs.redraw unless @cs.isDisposed
  end
end

#animate(n = 10, repaint = true, &blk) ⇒ Object



296
297
298
299
300
301
# File 'lib/shoes/app.rb', line 296

def animate n=10, repaint=true, &blk
  n, i = 1000 / n, 0
  Anim.new(@cs, n, repaint, &blk).tap do |a|
    Shoes.display.timerExec n, a
  end
end

#arc(l, t, w, h, a1, a2, args = {}) ⇒ Object



436
437
438
439
440
441
# File 'lib/shoes/app.rb', line 436

def arc l, t, w, h, a1, a2, args={}
  a1 = a1 * 180 / Math::PI
  a2 = -a2 * 180 / Math::PI
  args.merge!({angle1: a1, angle2: a2})
  oval  l, t, w, h, args
end

#arrow(*attrs) ⇒ Object



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
# File 'lib/shoes/app.rb', line 622

def arrow *attrs
  args = attrs.last.class == Hash ? attrs.pop : {}
  w = attrs[2]
  args.merge!({left: attrs[0], top: attrs[1], width: w, height: w})
  shape args do
    move_to 0, w*0.5*0.6
    line_to w*0.58, w*0.5*0.6
    line_to w*0.58, w*0.5*0.2
    line_to w, w*0.5
    line_to w*0.58, w*(1-0.5*0.2)
    line_to w*0.58, w*(1-0.5*0.6)
    line_to 0, w*(1-0.5*0.6)
    line_to 0, w*0.5*0.6
  end
end

#background(pat, args = {}) ⇒ Object



693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
# File 'lib/shoes/app.rb', line 693

def background pat, args={}
  args[:pattern] = pat
  args = basic_attributes args
  args[:curve] ||= 0
  args[:real] = args[:create_real] ? :pattern : false
  args[:app] = self
  Background.new(args).tap do |s|
    unless s.real
      pat = s.pattern
      pl = Swt::PaintListener.new
      s.pl = pl
      class << pl; self end.
      instance_eval do
        define_method :paintControl do |e|
          unless s.hided
            gc = e.gc
            Shoes.dps_reset s.dps, gc
            gc.setAntialias Swt::SWT::ON
            Shoes.set_pattern s, gc, pat
            gc.fillRoundRectangle s.left, s.top, s.width, s.height, s.curve*2, s.curve*2
          end
        end
      end
      @cs.addPaintListener pl unless @cs.isDisposed
    end
    oval 0, 0, 0, strokewidth: 0 # A monkey patch for sample 10. I don't know why this line is necessary... xx-P
  end
end


137
# File 'lib/shoes/app.rb', line 137

def banner *msg; textblock Banner, 48, *msg; end

#basic_attributes(args = {}) ⇒ Object



49
50
51
52
53
54
# File 'lib/shoes/helper_methods.rb', line 49

def basic_attributes args={}
  default = BASIC_ATTRIBUTES_DEFAULT
  default.merge!({nocontrol: true}) if @nolayout
  replace_string_to_float args
  default.merge args
end

#border(pat, args = {}) ⇒ Object



722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
# File 'lib/shoes/app.rb', line 722

def border pat, args={}
  args[:pattern] = pat
  args = basic_attributes args
  args[:curve] ||= 0
  args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
  args[:real] = args[:create_real] ? :pattern : false
  args[:app] = self
  Border.new(args).tap do |s|
    unless s.real
      pat = s.pattern
      sw = s.strokewidth
      pl = Swt::PaintListener.new
      s.pl = pl
      class << pl; self end.
      instance_eval do
        define_method :paintControl do |e|
          unless s.hided
            gc = e.gc
            Shoes.dps_reset s.dps, gc
            gc.setAntialias Swt::SWT::ON
            Shoes.set_pattern s, gc, pat, :Foreground
            if sw > 0
              gc.setLineWidth sw
              gc.drawRoundRectangle s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.curve*2, s.curve*2
            end
          end
        end
      end
      @cs.addPaintListener pl unless @cs.isDisposed
    end
  end
end

#button(name, args = {}, &blk) ⇒ Object



221
222
223
# File 'lib/shoes/app.rb', line 221

def button name, args={}, &blk
  buttonbase Button, name, args, &blk
end

#buttonbase(klass, name, args, &blk) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/shoes/app.rb', line 197

def buttonbase klass, name, args, &blk
  args = basic_attributes args
  args[:block] = blk
  opt = if klass == Button then Swt::SWT::NULL
    elsif klass == Radio then Swt::SWT::RADIO
    elsif klass == Check then Swt::SWT::CHECK end
  b = Swt::Button.new @cs, opt
  b.setVisible false if args[:hidden]
  args.delete :hidden
  b.setText name if klass == Button
  b.setLocation args[:left], args[:top]
  if args[:width] > 0 and args[:height] > 0
    b.setSize args[:width], args[:height]
  else
    b.pack
  end
  args[:real], args[:text], args[:app] = b, name, self
  klass.new(args).tap do |s|
    b.addSelectionListener do |e|
      klass == Button ? blk[s] : (blk[s] if b.getSelection)
    end if blk
  end
end

#cap(*line_cap) ⇒ Object



837
838
839
840
841
842
843
844
# File 'lib/shoes/app.rb', line 837

def cap *line_cap
  @line_cap = case line_cap.first
    when :curve, :rect, :project
      LINECAP[line_cap.first]
    else
      @line_cap ||= LINECAP[:rect]
  end
end

#caption(*msg) ⇒ Object



141
# File 'lib/shoes/app.rb', line 141

def caption *msg; textblock Caption, 14, *msg; end

#check(args = {}, &blk) ⇒ Object



229
230
231
# File 'lib/shoes/app.rb', line 229

def check args={}, &blk
  buttonbase Check, nil, args, &blk
end

#clear(&blk) ⇒ Object



56
57
58
59
# File 'lib/shoes/app.rb', line 56

def clear &blk
  @top_slot.clear &blk
  aflush
end

#click(&blk) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/shoes/app.rb', line 61

def click &blk
  if blk
    app = self
    Swt::Listener.new.tap do |ln|
      class << ln; self end.
      instance_eval do
        define_method(:handleEvent){|e| blk[*app.mouse]}
        define_method(:clear){app.cs.removeListener Swt::SWT::MouseDown, ln}
      end
      @cs.addListener Swt::SWT::MouseDown, ln unless @cs.isDisposed
    end
  end
end

#clickable(s, flag = :click, &blk) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/shoes/helper_methods.rb', line 70

def clickable s, flag = :click, &blk
  if blk
    ln = Swt::Listener.new
    s.ln = ln
    @mscs << s
    class << ln; self end.
    instance_eval do
      define_method :handleEvent do |e|
        mb, mx, my = e.button, e.x, e.y
        if s.is_a?(Link) and !s.parent.hided
          blk[mb, mx, my] if ((s.pl..(s.pl+s.pw)).include?(mx) and (s.sy..s.ey).include?(my) and !((s.pl..s.sx).include?(mx) and (s.sy..(s.sy+s.lh)).include?(my)) and !((s.ex..(s.pl+s.pw)).include?(mx) and ((s.ey-s.lh)..s.ey).include?(my)))
        elsif !s.is_a?(Link) and !s.hided
          dx, dy = s.is_a?(Star) ? [s.width / 2.0, s.height / 2.0] : [0, 0]
          blk[mb, mx, my] if s.left - dx <= mx and mx <= s.left - dx + s.width and s.top - dy <= my and my <= s.top - dy + s.height
        end
      end
    end
    @cs.addListener Swt::SWT::MouseDown, ln if flag == :click
    @cs.addListener Swt::SWT::MouseUp, ln if flag == :release
  end
end

#clipboardObject



792
793
794
# File 'lib/shoes/app.rb', line 792

def clipboard
  Swt::Clipboard.new(Shoes.display).getContents Swt::TextTransfer.getInstance
end

#clipboard=(str) ⇒ Object



796
797
798
# File 'lib/shoes/app.rb', line 796

def clipboard=(str)
  Swt::Toolkit.getDefaultToolkit.getSystemClipboard.setContents Swt::StringSelection.new(str), Shoes
end

#closeObject



800
801
802
803
# File 'lib/shoes/app.rb', line 800

def close
  @shell.close
  Shoes.APPS.delete self
end

#download(name, args = {}, &blk) ⇒ Object



771
772
773
# File 'lib/shoes/app.rb', line 771

def download name, args={}, &blk
  Download.new self, name, args, &blk
end

#edit_box(*attrs, &blk) ⇒ Object



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/shoes/app.rb', line 256

def edit_box *attrs, &blk
  app = self
  edit_text([EditBox, 200, 100, Swt::SWT::MULTI | Swt::SWT::WRAP, blk, attrs]).tap do |s|
    unless s.args[:accepts_tab]
      kl = Swt::KeyListener.new
      class << kl; self end.
      instance_eval do
        define_method :keyPressed do |e|
          if e.character == Swt::SWT::TAB
            e.doit = false
            list = app.cs.getTabList.to_a
            list[(list.index(s.real) + 1) % list.length].setFocus
          end
        end
        define_method(:keyReleased){|e|}
      end
      s.real.addKeyListener kl
    end
  end
end

#edit_line(*attrs, &blk) ⇒ Object



252
253
254
# File 'lib/shoes/app.rb', line 252

def edit_line *attrs, &blk
  edit_text [EditLine, 200, 20, Swt::SWT::SINGLE, blk, attrs]
end

#edit_text(attrs) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/shoes/app.rb', line 233

def edit_text attrs
  klass, w, h, style, blk, attrs = attrs
  args = attrs.last.class == Hash ? attrs.pop : {}
  txt = attrs.first unless attrs.empty?
  args = basic_attributes args
  args[:width] = w if args[:width].zero?
  args[:height] = h if args[:height].zero?
  
  el = Swt::Text.new @cs, Swt::SWT::BORDER | style
  el.setVisible false if args[:hidden]
  args.delete :hidden
  el.setText txt || args[:text].to_s
  el.setSize args[:width], args[:height]
  args[:real], args[:app] = el, self
  klass.new(args).tap do |s|
    el.addModifyListener{|e| blk[s]} if blk
  end      
end

#every(n = 1, &blk) ⇒ Object



303
304
305
# File 'lib/shoes/app.rb', line 303

def every n=1, &blk
  animate 1.0/n, &blk
end

#flow(args = {}, &blk) ⇒ Object



51
52
53
54
# File 'lib/shoes/app.rb', line 51

def flow args={}, &blk
  args[:app] = self
  Flow.new slot_attributes(args), &blk
end

#flushObject



810
811
812
813
814
815
# File 'lib/shoes/app.rb', line 810

def flush
  unless @cs.isDisposed
    Shoes.call_back_procs self
    @cs.redraw
  end
end

#font(name) ⇒ Object



20
21
22
# File 'lib/shoes/text.rb', line 20

def font name
  @font_family = name
end

#get_styles(msg, styles = [], spoint = 0) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/shoes/helper_methods.rb', line 92

def get_styles msg, styles=[], spoint=0
  msg.each do |e|
    if e.is_a? Text
      epoint = spoint + e.to_s.length - 1
      styles << [e, spoint..epoint]
      get_styles e.str, styles, spoint
    end
    spoint += e.to_s.length
  end
  styles
end

#gradient(*attrs) ⇒ Object



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
# File 'lib/shoes/app.rb', line 658

def gradient *attrs
  case attrs.length
    when 1, 2
      pat1, pat2 = attrs
      pat2 = pat1 unless pat2
      return tr_color(pat1)..tr_color(pat2)
    when 5, 6
      pat, l, t, w, h, angle = attrs
      angle = 0 unless angle
    else
    return black..black
  end

  pat = tr_color pat
  color = case pat
    when Range; [tr_color(pat.first), tr_color(pat.last)]
    when Array; [pat, pat]
    when String
      return Swt::Pattern.new(Shoes.display, Swt::Image.new(Shoes.display, pat))
    else
      [black, black]
  end
  Swt::Pattern.new Shoes.display, *pattern_pos(l, t, w, h, -angle), Swt::Color.new(Shoes.display, *color[0][0, 3]), Swt::Color.new(Shoes.display, *color[1][0, 3])
end

#gray(*attrs) ⇒ Object



832
833
834
835
# File 'lib/shoes/app.rb', line 832

def gray *attrs
  g, a = attrs
  g ? rgb(g*255, g*255, g*255, a) : rgb(128, 128, 128)[0..2]
end

#image(name, args = {}, &blk) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/shoes/app.rb', line 145

def image name, args={}, &blk
  args = basic_attributes args
  args[:rotate] ||= rotate
  if name =~ /^(http|https):\/\//
    tmpname = File.join(Dir.tmpdir, "__purple_shoes_#{Time.now.to_f}.png")
    url, name = name, File.join(DIR, '../static/downloading.png')
  end
  img = Swt::Image.new Shoes.display, name
  args[:full_width], args[:full_height] = imagesize(name)
  args[:real], args[:app] = img, self
  
  Image.new(args).tap do |s|
    download url, save: tmpname do
      tmp = Swt::Image.new Shoes.display, tmpname
      s.real = tmp
      s.full_width, s.full_height = tmp.getImageData.width, tmp.getImageData.height
      if s.initials[:width].zero? and s.initials[:height].zero?
        s.width, s.height = s.full_width, s.full_height
      end
      File.delete tmpname
    end if url

    pl = Swt::PaintListener.new
    s.pl = pl
    class << pl; self end.
    instance_eval do
      define_method :paintControl do |e|
        gc = e.gc
        Shoes.dps_reset s.dps, gc
        unless s.hided
          Shoes.set_rotate e.gc, *s.rotate do
            if s.initials[:width].zero? and s.initials[:height].zero?
              gc.drawImage s.real, s.left, s.top
            else
              s.width = s.full_width if s.width.zero?
              s.height = s.full_height if s.height.zero?
              gc.drawImage s.real, 0, 0, s.full_width, s.full_height, s.left, s.top, s.width, s.height
            end
          end
        end
      end
    end
    @cs.addPaintListener pl unless @cs.isDisposed
    clickable s, &blk
  end
end

#imagesize(name) ⇒ Object



192
193
194
195
# File 'lib/shoes/app.rb', line 192

def imagesize name
  img = Swt::Image.new Shoes.display, name
  return img.getImageData.width, img.getImageData.height
end

#inscription(*msg) ⇒ Object



143
# File 'lib/shoes/app.rb', line 143

def inscription *msg; textblock Para, 10, *msg; end

#keypress(&blk) ⇒ Object



316
317
318
319
320
321
322
323
324
325
326
# File 'lib/shoes/app.rb', line 316

def keypress &blk
  Swt::KeyListener.new.tap do |kl|
    class << kl; self end.
    instance_eval do
      define_method(:keyPressed){|e| blk[KEY_NAMES[e.keyCode] || e.character.chr]}
      define_method(:keyReleased){|e|}
      define_method(:clear){Shoes.shell.removeKeyListener kl}
    end
    @shell.addKeyListener kl
  end
end

#line(*attrs, &blk) ⇒ Object



499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'lib/shoes/app.rb', line 499

def line *attrs, &blk
  args = attrs.last.class == Hash ? attrs.pop : {}
  case attrs.length
    when 0, 1, 2
    when 3; args[:sx], args[:sy], args[:ex] = attrs; args[:ey] = args[:ex]
    else args[:sx], args[:sy], args[:ex], args[:ey] = attrs
  end
  sx, sy, ex, ey = args[:sx], args[:sy], args[:ex], args[:ey]
  sw = args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
  cw = hsw = sw*0.5
  args[:width], args[:height] = (sx - ex).abs, (sy - ey).abs
  args[:width] += cw
  args[:height] += cw
  args[:nocontrol] = args[:noorder] = true
  args = basic_attributes args
  
  if ((sx - ex) < 0 and (sy - ey) < 0) or ((sx - ex) > 0 and (sy - ey) > 0)
    args[:left] = (sx - ex) < 0 ? sx - hsw : ex - hsw
    args[:top] = (sy - ey) < 0 ? sy - hsw : ey - hsw
  elsif ((sx - ex) < 0 and (sy - ey) > 0) or ((sx - ex) > 0 and (sy - ey) < 0)
    args[:left] = (sx - ex) < 0 ? sx - hsw : ex - hsw
    args[:top] = (sy - ey) < 0 ? sy - hsw : ey - hsw
  elsif !(sx - ex).zero? and (sy - ey).zero?
    args[:left] = (sx - ex) < 0 ? sx : ex
    args[:top] = (sy - ey) < 0 ? sy - hsw : ey - hsw
  elsif (sx - ex).zero? and !(sy - ey).zero?
    args[:left] = (sx - ex) < 0 ? sx - hsw : ex - hsw
    args[:top] = (sy - ey) < 0 ? sy : ey
  else
    args[:left] = sw
    args[:top] = sy
  end

  args[:stroke] ||= stroke
  args[:rotate] ||= rotate
  args[:cap] = (LINECAP[args[:cap]] or cap)
  args[:real], args[:app] = :shape, self
  Line.new(args).tap do |s|
    pl = Swt::PaintListener.new
    s.pl = pl
    class << pl; self end.
    instance_eval do
      define_method :paintControl do |e|
        unless s.hided
          gc = e.gc
          Shoes.dps_reset s.dps, gc
          gc.setAntialias Swt::SWT::ON
          gc.setLineCap s.cap
          sw, pat = s.strokewidth, s.stroke
          Shoes.set_rotate gc, *s.rotate do
            if pat
              Shoes.set_pattern s, gc, pat, :Foreground
              if sw > 0
                gc.setLineWidth sw
                gc.drawLine s.sx, s.sy, s.ex, s.ey
              end
            end
          end
        end
      end
    end
    @cs.addPaintListener pl unless @cs.isDisposed
    clickable s, &blk
  end
end


16
17
18
# File 'lib/shoes/text.rb', line 16

def link *str, &blk
  Link.new :link, str, &blk
end

#list_box(args = {}) ⇒ Object



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/shoes/app.rb', line 277

def list_box args={}
  args = basic_attributes args
  args[:width] = 200 if args[:width].zero?
  args[:height] = 20 if args[:height].zero?
  args[:items] ||= []
  cb = Swt::Combo.new @cs, Swt::SWT::DROP_DOWN
  cb.setVisible false if args[:hidden]
  args.delete :hidden
  cb.setSize args[:width], args[:height]
  cb.setItems args[:items].map(&:to_s)
  cb.setText args[:choose].to_s
  args[:real], args[:app] = cb, self
  ListBox.new(args).tap do |s|
    cb.addSelectionListener do |e|
      yield s
    end if block_given?
  end
end

#motion(&blk) ⇒ Object



312
313
314
# File 'lib/shoes/app.rb', line 312

def motion &blk
  @mmcs << blk
end

#mouseObject



328
329
330
# File 'lib/shoes/app.rb', line 328

def mouse
  [@mouse_button, @mouse_pos[0], @mouse_pos[1]]
end

#nested_styles(styles, st) ⇒ Object



172
173
174
175
176
# File 'lib/shoes/helper_methods.rb', line 172

def nested_styles styles, st
  styles.map do |e|
    (e[1].first <= st[1].first and st[1].last <= e[1].last) ? e : nil
  end - [nil]
end

#nofillObject



654
655
656
# File 'lib/shoes/app.rb', line 654

def nofill
  @fill = false
end

#nostrokeObject



650
651
652
# File 'lib/shoes/app.rb', line 650

def nostroke
  strokewidth 0
end

#oval(*attrs, &blk) ⇒ Object



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/shoes/app.rb', line 377

def oval *attrs, &blk
  args = attrs.last.class == Hash ? attrs.pop : {}
  case attrs.length
    when 0, 1
    when 2; args[:left], args[:top] = attrs
    when 3; args[:left], args[:top], args[:radius] = attrs
    else args[:left], args[:top], args[:width], args[:height] = attrs
  end
  args = basic_attributes args
  args[:width].zero? ? (args[:width] = args[:radius] * 2) : (args[:radius] = args[:width]/2.0)
  args[:height] = args[:width] if args[:height].zero?
  if args[:center]
    args[:left] -= args[:width] / 2
    args[:top] -= args[:height] / 2
  end
  args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
  args[:nocontrol] = args[:noorder] = true

  args[:stroke] ||= stroke
  args[:fill] ||= fill
  args[:rotate] ||= rotate
  args[:cap] = (LINECAP[args[:cap]] or cap)
  args[:real], args[:app] = :shape, self
  args[:angle1] = false unless args[:angle1]
  Oval.new(args).tap do |s|
    pl = Swt::PaintListener.new
    s.pl = pl
    class << pl; self end.
    instance_eval do
      define_method :paintControl do |e|
        unless s.hided
          gc = e.gc
          Shoes.dps_reset s.dps, gc
          gc.setAntialias Swt::SWT::ON
          gc.setLineCap s.cap
          sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
          Shoes.set_rotate gc, *s.rotate do
            if pat2
              Shoes.set_pattern s, gc, pat2
              s.angle1 ? gc.fillArc(s.left+sw, s.top+sw, s.width-sw*2, s.height-sw*2, s.angle1, s.angle2) : 
                gc.fillOval(s.left+sw, s.top+sw, s.width-sw*2, s.height-sw*2)
            end
            if pat1
              Shoes.set_pattern s, gc, pat1, :Foreground
              if sw > 0
                gc.setLineWidth sw
                s.angle1 ? gc.drawArc(s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.angle1, s.angle2) : 
                  gc.drawOval(s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw)
              end
            end
          end
        end
      end
    end
    @cs.addPaintListener pl unless @cs.isDisposed
    clickable s, &blk
  end
end

#para(*msg) ⇒ Object



142
# File 'lib/shoes/app.rb', line 142

def para *msg; textblock Para, 12, *msg; end

#pattern_pos(left, top, w, h, a) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/shoes/helper_methods.rb', line 178

def pattern_pos left, top, w, h, a
  w, h = w*0.5, h*0.5
  a = Math::PI*(a/180.0)
  a = a % (Math::PI*2.0)
  cal = proc do
    l = Math.sqrt(w**2 + h**2)
    b = Math.atan(h/w)
    c = Math::PI*0.5 - a - b
    r = l * Math.cos(c.abs)
    [r * Math.cos(b+c), r * Math.sin(b+c)]
  end
  if 0 <= a and a < Math::PI*0.5
    x, y = cal.call
    [left+w+x, top+h-y, left+w-x, top+h+y]
  elsif Math::PI*0.5 <= a and a < Math::PI
    a -= Math::PI*0.5
    w, h = h, w
    x, y = cal.call
    [left+h+y, top+w+x, left+h-y, top+w-x]
  elsif Math::PI <= a and a < Math::PI*1.5
    a -= Math::PI
    x, y = cal.call
    [left+w-x, top+h+y, left+w+x, top+h-y]
  elsif Math::PI*1.5 <= a and a < Math::PI*2.0
    a -= Math::PI*1.5
    w, h = h, w
    x, y = cal.call
    [left+h-y, top+w-x, left+h+y, top+w+x]
  end
end

#progress(args = {}) ⇒ Object



755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
# File 'lib/shoes/app.rb', line 755

def progress args={}
  pb = Swt::ProgressBar.new @cs, Swt::SWT::SMOOTH
  if args[:left] or args[:top]
    args[:noorder] = args[:nocontrol] = true
  end
  args[:width] ||= 150
  args[:height] ||= 16
  args = basic_attributes args
  pb.setVisible false if args[:hidden]
  args.delete :hidden
  pb.setSize args[:width], args[:height]
  pb.setLocation args[:left], args[:top]
  args[:real], args[:app] = pb, self
  Progress.new args
end

#radio(args = {}, &blk) ⇒ Object



225
226
227
# File 'lib/shoes/app.rb', line 225

def radio args={}, &blk
  buttonbase Radio, nil, args, &blk
end

#rect(*attrs, &blk) ⇒ Object



443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/shoes/app.rb', line 443

def rect *attrs, &blk
  args = attrs.last.class == Hash ? attrs.pop : {}
  case attrs.length
    when 0, 1
    when 2; args[:left], args[:top] = attrs
    when 3; args[:left], args[:top], args[:width] = attrs
    else args[:left], args[:top], args[:width], args[:height] = attrs
  end
  args[:height] = args[:width] unless args[:height]
  if args[:center]
    args[:left] -= args[:width] / 2
    args[:top] -= args[:height] / 2
  end
  args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
  args[:curve] ||= 0
  args[:nocontrol] = args[:noorder] = true
  args = basic_attributes args

  args[:stroke] ||= stroke
  args[:fill] ||= fill
  args[:rotate] ||= rotate
  args[:cap] = (LINECAP[args[:cap]] or cap)
  args[:real], args[:app] = :shape, self
  Rect.new(args).tap do |s|
    pl = Swt::PaintListener.new
    s.pl = pl
    class << pl; self end.
    instance_eval do
      define_method :paintControl do |e|
        unless s.hided
          gc = e.gc
          Shoes.dps_reset s.dps, gc
          gc.setAntialias Swt::SWT::ON
          gc.setLineCap s.cap
          sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
          Shoes.set_rotate gc, *s.rotate do
            if pat2
              Shoes.set_pattern s, gc, pat2
              gc.fillRoundRectangle s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.curve*2, s.curve*2
            end
            if pat1
              Shoes.set_pattern s, gc, pat1, :Foreground
              if sw > 0
                gc.setLineWidth sw
                gc.drawRoundRectangle s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.curve*2, s.curve*2
              end
            end
          end
        end
      end
    end
    @cs.addPaintListener pl unless @cs.isDisposed
    clickable s, &blk
  end
end

#replace_string_to_float(args = {}) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/shoes/helper_methods.rb', line 62

def replace_string_to_float args={}
  [:width, :height, :left, :top].each do |k|
    if args[k].is_a? String
      args[k] = args[k].include?('%') ? args[k].to_f / 100 : args[k].to_i
    end
  end
end

#rgb(r, g, b, l = 1.0) ⇒ Object



638
639
640
# File 'lib/shoes/app.rb', line 638

def rgb r, g, b, l=1.0
  (r <= 1 and g <= 1 and b <= 1) ? [r*255, g*255, b*255, l] : [r, g, b, l]
end

#rotate(angle = nil, left = 0, top = 0) ⇒ Object



646
647
648
# File 'lib/shoes/app.rb', line 646

def rotate angle=nil, left=0, top=0
  angle ? @rotate = [angle, left, top] : @rotate ||= [0, 0, 0]
end

#scroll_heightObject



784
785
786
# File 'lib/shoes/app.rb', line 784

def scroll_height
  scroll_max + height
end

#scroll_maxObject



788
789
790
# File 'lib/shoes/app.rb', line 788

def scroll_max
  shell.getVerticalBar.getMaximum - 10
end

#scroll_topObject



775
776
777
# File 'lib/shoes/app.rb', line 775

def scroll_top
  cs.getLocation.y
end

#scroll_top=(n) ⇒ Object



779
780
781
782
# File 'lib/shoes/app.rb', line 779

def scroll_top=(n)
  cs.setLocation 0, -n
  shell.getVerticalBar.setSelection n
end

#set_styles(s, args) ⇒ Object



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
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/shoes/helper_methods.rb', line 104

def set_styles s, args
  tl = s.real
  tl.setJustify args[:justify]
  tl.setSpacing(args[:leading] || 4)
  tl.setAlignment case args[:align]
    when 'center'; Swt::SWT::CENTER
    when 'right'; Swt::SWT::RIGHT
    else Swt::SWT::LEFT
    end
  font = Swt::Font.new Shoes.display, args[:font], args[:size], Swt::SWT::NORMAL
  fgc = Swt::Color.new Shoes.display, *args[:stroke]
  bgc = args[:fill] ? Swt::Color.new(Shoes.display, *args[:fill]) : nil
  style = Swt::TextStyle.new font, fgc, bgc
  tl.setStyle style, 0, args[:markup].length - 1
  s.dps << font << fgc << bgc
  
  args[:styles].each do |st|
    font, ft, fg, bg, cmds, small = args[:font], Swt::SWT::NORMAL, fgc, bgc, [], 1
    nested_styles(args[:styles], st).each do |e|
      case e[0].style
      when :strong
        ft = ft | Swt::SWT::BOLD
      when :em
        ft = ft | Swt::SWT::ITALIC 
      when :fg
        fg = Swt::Color.new Shoes.display, *e[0].color[0,3]
      when :bg
        bg = Swt::Color.new Shoes.display, *e[0].color[0,3]
      when :ins
        cmds << "underline = true"
      when :del
        cmds << "strikeout = true"
      when :sub
        small *= 0.8
        cmds << "rise = -5"
      when :sup
        small *= 0.8
        cmds << "rise = 5"
      when :code
        font = "Lucida Console"
      when :link
        (cmds << "underline = true") if LINK_DEFAULT[:underline]
        fg = Swt::Color.new Shoes.display, *blue
        spos = tl.getLocation e[1].first, false
        epos = tl.getLocation e[1].last, true
        e[0].lh = tl.getLineBounds(0).height
        e[0].sx, e[0].sy = s.left + spos.x, s.top + spos.y
        e[0].ex, e[0].ey = s.left + epos.x, s.top + epos.y + e[0].lh
        e[0].pl, e[0].pt, e[0].pw, e[0].ph = s.left, s.top, s.width, s.height
        s.links << e[0]
        unless e[0].clickabled
          e[0].parent = s
          clickable e[0], &e[0].blk
          e[0].clickabled = true
        end
      else
      end
    end
    ft = Swt::Font.new Shoes.display, font, args[:size]*small, ft
    style = Swt::TextStyle.new ft, fg, bg
    cmds.each do |cmd|
      eval "style.#{cmd}"
    end
    tl.setStyle style, st[1].first, st[1].last
    s.dps << ft
  end if args[:styles]
end

#shape(args = {}, &blk) ⇒ Object



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/shoes/app.rb', line 332

def shape args={}, &blk
  args = basic_attributes args
  args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
  args[:nocontrol] = args[:noorder] = true
  args[:stroke] ||= stroke
  args[:fill] ||= fill
  args[:rotate] ||= rotate
  args[:cap] = (LINECAP[args[:cap]] or cap)
  args[:real], args[:app], args[:block] = :shape, self, blk
  Shape.new(args).tap do |s|
    pl = Swt::PaintListener.new
    s.pl = pl
    s.real = Swt::Path.new Shoes.display
    class << pl; self end.
    instance_eval do
      define_method :paintControl do |e|
        unless s.hided
          s.real = Swt::Path.new(Shoes.display) if s.real.isDisposed
          gc = e.gc
          Shoes.dps_reset s.dps, gc
          gc.setAntialias Swt::SWT::ON
          gc.setLineCap s.cap
          sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
          Shoes.set_rotate gc, *s.rotate do
            if pat2
              Shoes.set_pattern s, gc, pat2
              s.instance_eval &s.block
              gc.fillPath s.real
            end
            if pat1
              Shoes.set_pattern s, gc, pat1, :Foreground
              if sw > 0
                gc.setLineWidth sw
                s.instance_eval &s.block
                gc.drawPath s.real
              end
            end
          end
        end
      end
    end
    @cs.addPaintListener pl unless @cs.isDisposed
  end
end

#slot_attributes(args = {}) ⇒ Object



56
57
58
59
60
# File 'lib/shoes/helper_methods.rb', line 56

def slot_attributes args={}
  default = SLOT_ATTRIBUTES_DEFAULT
  replace_string_to_float args
  default.merge args
end

#stack(args = {}, &blk) ⇒ Object



46
47
48
49
# File 'lib/shoes/app.rb', line 46

def stack args={}, &blk
  args[:app] = self
  Stack.new slot_attributes(args), &blk
end

#star(*attrs, &blk) ⇒ Object



565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
# File 'lib/shoes/app.rb', line 565

def star *attrs, &blk
  args = attrs.last.class == Hash ? attrs.pop : {}
  case attrs.length
    when 2; args[:left], args[:top] = attrs
    when 5; args[:left], args[:top], args[:points], args[:outer], args[:inner] = attrs
    else
  end
  args[:points] ||= 10; args[:outer] ||= 100.0; args[:inner] ||= 50.0
  args[:width] = args[:height] = args[:outer]*2.0
  args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
  args[:nocontrol] = args[:noorder] = true
  args[:stroke] ||= stroke
  args[:fill] ||= fill
  args[:rotate] ||= rotate
  args[:cap] = (LINECAP[args[:cap]] or cap)
  args[:real], args[:app] = :shape, self
  Star.new(args).tap do |s|
    pl = Swt::PaintListener.new
    s.pl = pl
    class << pl; self end.
    instance_eval do
      define_method :paintControl do |e|
        unless s.hided
          gc = e.gc
          Shoes.dps_reset s.dps, gc
          gc.setAntialias Swt::SWT::ON
          gc.setLineCap s.cap
          sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
          outer, inner, points, left, top = s.outer, s.inner, s.points, s.left, s.top
          polygon = []
          polygon << left << (top + outer)
          (1..points*2).each do |i|
            angle =  i * Math::PI / points
            r = (i % 2 == 0) ? outer : inner
            polygon << (left + r * Math.sin(angle)) << (top + r * Math.cos(angle))
          end
          Shoes.set_rotate gc, *s.rotate do
            if pat2
              Shoes.set_pattern s, gc, pat2
              gc.fillPolygon polygon
            end
            if pat1
              Shoes.set_pattern s, gc, pat1, :Foreground
              if sw > 0
                gc.setLineWidth sw
                gc.drawPolygon polygon
              end
            end
          end
        end
      end
    end
    @cs.addPaintListener pl unless @cs.isDisposed
    clickable s, &blk
  end
end

#style(klass, args = {}) ⇒ Object



3
4
5
6
7
# File 'lib/shoes/style.rb', line 3

def style klass, args={}
  if klass.superclass == Shoes::TextBlock or klass == Shoes::Link
    eval("#{klass.to_s[7..-1].upcase}_DEFAULT").clear.merge! args
  end
end

#subtitle(*msg) ⇒ Object



139
# File 'lib/shoes/app.rb', line 139

def subtitle *msg; textblock Subtitle, 26, *msg; end

#tagline(*msg) ⇒ Object



140
# File 'lib/shoes/app.rb', line 140

def tagline *msg; textblock Tagline, 18, *msg; end

#textblock(klass, font_size, *msg) ⇒ Object



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
# File 'lib/shoes/app.rb', line 75

def textblock klass, font_size, *msg
  args = msg.last.class == Hash ? msg.pop : {}
  args = eval("#{klass.to_s[7..-1].upcase}_DEFAULT").merge args
  args = basic_attributes args
  args[:contents] = msg
  args[:markup] = msg.map(&:to_s).join

  styles = get_styles msg
  args[:styles] = styles unless styles.empty?

  args[:size] ||= font_size
  args[:font] ||= (@font_family or 'sans')
  args[:stroke] ||= black
  args[:rotate] ||= rotate
  
  unless args[:left].zero? and args[:top].zero?
    args[:nocontrol], args[:width] = true, width
    layout_control = false
  else
    layout_control = true
  end

  args[:real] = (args[:create_real] or !layout_control) ? :textblock : false
  args[:app] = self
  
  klass.new(args).tap do |s|
    unless s.real and layout_control
      s.contents.each{|e| e.parent = s if e.is_a?(Text)}
      tl = Swt::TextLayout.new Shoes.display
      s.real = tl
      pl = Swt::PaintListener.new
      s.pl = pl
      class << pl; self end.
      instance_eval do
        define_method :paintControl do |e|
          gc = e.gc
          Shoes.dps_reset s.dps, gc
          tl.setText s.markup
          s.app.set_styles s, s.args
          tl.setWidth s.width if s.width > 0
          unless s.hided
            Shoes.set_rotate gc, *s.rotate do
              tl.draw gc, s.left, s.top
            end
            if s.cursor
              h = s.real.getLineBounds(0).height
              s.textcursor ||= s.app.line(0, 0, 0, h, strokewidth: 1, stroke: s.app.black, hidden: true)
              n = s.cursor == -1 ? s.text.length - 1 : s.cursor
              n = 0 if n < 0
              pos = s.real.getLocation n, true
              s.textcursor.move(s.left + pos.x, s.top + pos.y).show
            else
              (s.textcursor.clear; s.textcursor = nil) if s.textcursor
            end
          end
        end
      end
      @cs.addPaintListener pl unless @cs.isDisposed
    end
  end
end

#timer(n = 1, &blk) ⇒ Object



307
308
309
310
# File 'lib/shoes/app.rb', line 307

def timer n=1, &blk
  n *= 1000
  Timer.new(self, n, &blk).tap{|t| Shoes.display.timerExec n, t}
end

#title(*msg) ⇒ Object



138
# File 'lib/shoes/app.rb', line 138

def title *msg; textblock Title, 34, *msg; end

#tr_color(pat) ⇒ Object



683
684
685
686
687
688
689
690
691
# File 'lib/shoes/app.rb', line 683

def tr_color pat
  if pat.is_a?(String) and pat[0] == '#'
    color = pat[1..-1]
    color = color.gsub(/(.)/){$1 + '0'} if color.length == 3
    rgb *color.gsub(/(..)/).map{$1.hex}
  else
    pat
  end
end

#video(path, args = {}) ⇒ Object



102
103
104
105
# File 'lib/plugins/video.rb', line 102

def video path, args={}
  args = {left: 0, top: 0, width: 320, height: 240, app: self}.merge args
  Video.new path, args
end

#visit(url) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/shoes/app.rb', line 30

def visit url
  if url =~ /^(http|https):\/\//
    require 'rbconfig'
    Thread.new do
      case RbConfig::CONFIG['host_os']
      when /mswin/; system "start #{url}"
      when /linux/; system("/etc/alternatives/x-www-browser #{url} &")
      else
        puts "Sorry, your platform [#{RUBY_PLATFORM}] is not supported..."
      end
    end
  else
    $urls.each{|k, v| clear{init_app_vars; @location = url; v.call self, $1} if k =~ url}
  end
end

#window(args = {}, &blk) ⇒ Object



805
806
807
808
# File 'lib/shoes/app.rb', line 805

def window args={}, &blk
  args.merge! owner: self
  Shoes.app args, &blk
end