1# toolbar.rb --
2#
3# This demonstration script creates a toolbar that can be torn off.
4#
5# based on "Id: toolbar.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
6
7if defined?($toolbar_demo) && $toolbar_demo
8  $toolbar_demo.destroy
9  $toolbar_demo = nil
10end
11
12$toolbar_demo = TkToplevel.new {|w|
13  title("Ttk Menu Buttons")
14  iconname("toolbar")
15  positionWindow(w)
16}
17
18base_frame = Ttk::Frame.new($toolbar_demo).pack(:fill=>:both, :expand=>true)
19
20if Tk.windowingsystem != 'aqua'
21  msg = Ttk::Label.new(base_frame, :wraplength=>'4i',
22                       :text=>Tk::UTF8_String.new(<<EOL))
23This is a demonstration of how to do \
24a toolbar that is styled correctly \
25and which can be torn off (this feature reqrires Tcl/Tk8.5). \
26The buttons are configured to be \\u201Ctoolbar style\\u201D buttons by \
27telling them that they are to use the Toolbutton style. At the left \
28end of the toolbar is a simple marker that the cursor changes to a \
29movement icon over; drag that away from the toolbar to tear off the \
30whole toolbar into a separate toplevel widget. When the dragged-off \
31toolbar is no longer needed, just close it like any normal toplevel \
32and it will reattach to the window it was torn off from.
33EOL
34else
35  msg = Ttk::Label.new(base_frame, :wraplength=>'4i',
36                       :text=>Tk::UTF8_String.new(<<EOL))
37This is a demonstration of how to do \
38a toolbar that is styled correctly. The buttons are configured to \
39be \\u201Ctoolbar style\\u201D buttons by telling them that they are \
40to use the Toolbutton style.
41EOL
42end
43
44## Set up the toolbar hull
45tbar_base = Tk::Frame.new(base_frame, # Must be a starndard Tk frame!
46                          :widgetname=>'toolbar') # for window title
47sep = Ttk::Separator.new(base_frame)
48to_base = Ttk::Frame.new(tbar_base, :cursor=>'fleur')
49if Tk.windowingsystem != 'aqua'
50  to  = Ttk::Separator.new(to_base, :orient=>:vertical)
51  to2 = Ttk::Separator.new(to_base, :orient=>:vertical)
52  to.pack(:fill=>:y, :expand=>true, :padx=>2, :side=>:left)
53  to2.pack(:fill=>:y, :expand=>true, :side=>:left)
54end
55
56contents = Ttk::Frame.new(tbar_base)
57Tk.grid(to_base, contents, :sticky=>'nsew')
58tbar_base.grid_columnconfigure(contents, :weight=>1)
59contents.grid_columnconfigure(1000, :weight=>1)
60
61if Tk.windowingsystem != 'aqua'
62  ## Bindings so that the toolbar can be torn off and reattached
63  to_base.bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
64  to.     bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
65  to2.    bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
66  def tbar_base.tearoff(w, x, y)
67    on_win = TkWinfo.containing(x, y)
68    return unless (on_win && on_win.path =~ /^#{@path}(\.|$)/)
69    self.grid_remove
70    w.grid_remove
71    self.wm_manage
72    # self.wm_title('Toolbar') # if you don't want to use its widget name as a window title.
73    self.wm_protocol('WM_DELETE_WINDOW'){ self.untearoff(w) }
74  end
75  def tbar_base.untearoff(w)
76    self.wm_forget
77    w.grid
78    self.grid
79  end
80end
81
82## Some content for the rest of the toplevel
83text = TkText.new(base_frame, :width=>40, :height=>10)
84
85## Toolbar contents
86tb_btn = Ttk::Button.new(tbar_base, :text=>'Button', :style=>'Toolbutton',
87                         :command=>proc{text.insert(:end, "Button Pressed\n")})
88tb_chk = Ttk::Checkbutton.new(tbar_base, :text=>'Check', :style=>'Toolbutton',
89                              :variable=>(check = TkVariable.new),
90                              :command=>proc{
91                                text.insert(:end, "Check is #{check.value}\n")
92                              })
93tb_mbtn = Ttk::Menubutton.new(tbar_base, :text=>'Menu')
94tb_combo = Ttk::Combobox.new(tbar_base, :value=>TkFont.families,
95                             :state=>:readonly)
96tb_mbtn.menu(menu = Tk::Menu.new(tb_mbtn))
97menu.add(:command, :label=>'Just', :command=>proc{text.insert(:end, "Just\n")})
98menu.add(:command, :label=>'An', :command=>proc{text.insert(:end, "An\n")})
99menu.add(:command, :label=>'Example',
100         :command=>proc{text.insert(:end, "Example\n")})
101tb_combo.bind('<ComboboxSelected>'){ text.font.family = tb_combo.get }
102
103## Arrange contents
104Tk.grid(tb_btn, tb_chk, tb_mbtn, tb_combo,
105        :in=>contents, :padx=>2, :sticky=>'ns')
106Tk.grid(tbar_base, :sticky=>'ew')
107Tk.grid(sep, :sticky=>'ew')
108Tk.grid(msg, :sticky=>'ew')
109Tk.grid(text, :sticky=>'nsew')
110base_frame.grid_rowconfigure(text, :weight=>1)
111base_frame.grid_columnconfigure(text, :weight=>1)
112
113## See Code / Dismiss buttons
114Ttk::Frame.new(base_frame) {|frame|
115  sep = Ttk::Separator.new(frame)
116  Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
117  TkGrid('x',
118         Ttk::Button.new(frame, :text=>'See Code',
119                         :image=>$image['view'], :compound=>:left,
120                         :command=>proc{showCode 'toolbar'}),
121         Ttk::Button.new(frame, :text=>'Dismiss',
122                         :image=>$image['delete'], :compound=>:left,
123                         :command=>proc{
124                           $toolbar_demo.destroy
125                           $toolbar_demo = nil
126                         }),
127         :padx=>4, :pady=>4)
128  grid_columnconfigure(0, :weight=>1)
129  Tk.grid(frame, :sticky=>'ew')
130}
131