1# -*- coding: utf-8 -*-
2#
3# widet demo 'puzzle' (called by 'widget')
4#
5
6# toplevel widget が存在すれば削除する
7if defined?($puzzle_demo) && $puzzle_demo
8  $puzzle_demo.destroy
9  $puzzle_demo = nil
10end
11
12# demo 用の toplevel widget を生成
13$puzzle_demo = TkToplevel.new {|w|
14  title("15-Puzzle Demonstration")
15  iconname("15-Puzzle")
16  positionWindow(w)
17}
18
19base_frame = TkFrame.new($puzzle_demo).pack(:fill=>:both, :expand=>true)
20
21# label 生成
22msg = TkLabel.new(base_frame) {
23  font $font
24  wraplength '4i'
25  justify 'left'
26  text "下の15-パズルはボタンを集めてできています。空いている所の隣のピースをクリックすると、そのピースがその空いている場所にスライドします。この操作を続け、ピースがその数の順に上から下、左から右に並ぶようにしてください。"
27}
28msg.pack('side'=>'top')
29
30# frame 生成
31TkFrame.new(base_frame) {|frame|
32  TkButton.new(frame) {
33    #text '了解'
34    text '閉じる'
35    command proc{
36      tmppath = $puzzle_demo
37      $puzzle_demo = nil
38      tmppath.destroy
39    }
40  }.pack('side'=>'left', 'expand'=>'yes')
41
42  TkButton.new(frame) {
43    text 'コード参照'
44    command proc{showCode 'puzzle'}
45  }.pack('side'=>'left', 'expand'=>'yes')
46
47}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
48
49# frame 生成
50#
51# Special trick: scrollbar widget を生成してその trough color を用いることで
52#                空白部分のための暗色を選択し,設定する
53#
54begin
55  if Tk.windowingsystem() == 'aqua'
56    frameWidth  = 168
57    frameHeight = 168
58  elsif Tk.default_widget_set == :Ttk
59    frameWidth  = 148
60    frameHeight = 124
61  else
62    frameWidth  = 120
63    frameHeight = 120
64  end
65rescue
66  frameWidth  = 120
67  frameHeight = 120
68end
69
70# depend_on_button_width = true
71depend_on_button_width = false
72
73s = TkScrollbar.new(base_frame)
74base = TkFrame.new(base_frame) {
75  width  frameWidth
76  height frameHeight
77  borderwidth 2
78  relief 'sunken'
79  bg s['troughcolor']
80}
81s.destroy
82base.pack('side'=>'top', 'padx'=>'1c', 'pady'=>'1c')
83
84# proc のスコープを閉じるため,proc 生成メソッドを用意
85# こうしておかねば,ループ中で値が変化する num の影響を受けて
86# puzzleSwitch の第 2 引数が変化してしまい,期待通りにはならない.
87def def_puzzleswitch_proc(w, num)
88  proc{puzzleSwitch w, num}
89end
90
91$xpos = {}
92$ypos = {}
93order = [3,1,6,2,5,7,15,13,4,11,8,9,14,10,12]
94(0..14).each{|i|
95  num = order[i]
96  $xpos[num] = (i % 4) * 0.25
97  $ypos[num] = (i / 4) * 0.25
98  TkButton.new(base) {|w|
99    relief 'raised'
100    text num
101    highlightthickness 0
102    command def_puzzleswitch_proc(w, num)
103    if depend_on_button_width && (w.winfo_reqwidth * 4 > base.width)
104      base.width = w.winfo_reqwidth * 4
105    end
106  }.place('relx'=>$xpos[num], 'rely'=>$ypos[num],
107          'relwidth'=>0.25, 'relheight'=>0.25)
108}
109$xpos['space'] = 0.75
110$ypos['space'] = 0.75
111
112############
113def puzzleSwitch(w, num)
114  if ( ($ypos[num] >= ($ypos['space'] - 0.01))     \
115      && ($ypos[num] <= ($ypos['space'] + 0.01))   \
116      && ($xpos[num] >= ($xpos['space'] - 0.26))   \
117      && ($xpos[num] <= ($xpos['space'] + 0.26)))  \
118    || (($xpos[num] >= ($xpos['space'] - 0.01))    \
119        && ($xpos[num] <= ($xpos['space'] + 0.01)) \
120        && ($ypos[num] >= ($ypos['space'] - 0.26)) \
121        && ($ypos[num] <= ($ypos['space'] + 0.26)))
122    tmp = $xpos['space']
123    $xpos['space'] = $xpos[num]
124    $xpos[num] = tmp
125    tmp = $ypos['space']
126    $ypos['space'] = $ypos[num]
127    $ypos[num] = tmp
128    w.place('relx'=>$xpos[num], 'rely'=>$ypos[num])
129  end
130end
131
132