fxruby 1.6.1 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/doc/apes02.html +6 -6
- data/doc/apes03.html +11 -11
- data/doc/book.html +1 -1
- data/doc/build.html +63 -63
- data/doc/ch03s02.html +7 -7
- data/doc/ch03s03.html +18 -18
- data/doc/ch03s04.html +11 -11
- data/doc/ch03s05.html +14 -14
- data/doc/ch04s02.html +14 -14
- data/doc/ch04s03.html +15 -15
- data/doc/ch04s04.html +28 -28
- data/doc/ch05s02.html +49 -49
- data/doc/ch05s03.html +8 -8
- data/doc/changes.html +263 -193
- data/doc/clipboardtut.html +57 -45
- data/doc/cvs.html +10 -10
- data/doc/differences.html +4 -4
- data/doc/dragdroptut.html +50 -50
- data/doc/events.html +11 -11
- data/doc/examples.html +48 -48
- data/doc/gems.html +37 -37
- data/doc/goals.html +4 -4
- data/doc/implementation.html +4 -4
- data/doc/infosources.html +6 -6
- data/doc/library.html +19 -19
- data/doc/opengl.html +31 -31
- data/doc/pt01.html +1 -1
- data/doc/pt02.html +1 -1
- data/doc/scintilla.html +15 -15
- data/doc/style.css +3 -0
- data/doc/todo.html +5 -5
- data/doc/tutorial1.html +34 -34
- data/doc/unicode.html +56 -0
- data/ext/fox16/dialogs_wrap.cpp +38 -14
- data/ext/fox16/frames_wrap.cpp +856 -22
- data/ext/fox16/fx3d_wrap.cpp +169 -144
- data/ext/fox16/icons_wrap.cpp +24 -6
- data/ext/fox16/image_wrap.cpp +24 -6
- data/ext/fox16/label_wrap.cpp +23 -8
- data/ext/fox16/markfuncs.cpp +8 -1
- data/ext/fox16/mdi_wrap.cpp +53 -23
- data/ext/fox16/menu_wrap.cpp +43 -19
- data/ext/fox16/scintilla_wrap.cpp +31 -7
- data/ext/fox16/table_wrap.cpp +31 -7
- data/ext/fox16/text_wrap.cpp +31 -7
- data/ext/fox16/treelist_wrap.cpp +300 -276
- data/ext/fox16/ui_wrap.cpp +385 -26
- data/lib/fox16/aliases.rb +3 -0
- data/lib/fox16/version.rb +1 -1
- data/rdoc-sources/FXFoldingList.rb +2 -2
- data/tests/TC_FXDirList.rb +1 -1
- data/tests/TC_FXGLViewer.rb +2 -0
- data/tests/TC_FXHeader.rb +1 -1
- data/tests/TC_FXIconList.rb +1 -1
- data/tests/TC_FXId.rb +1 -1
- data/tests/TC_FXList.rb +1 -1
- data/tests/TC_FXListBox.rb +1 -1
- data/tests/TC_FXMenuCommand.rb +0 -14
- data/tests/TC_FXTable.rb +0 -32
- data/tests/TC_FXTableItem.rb +1 -1
- data/tests/TC_FXTreeList.rb +1 -1
- data/tests/TC_FXTreeListBox.rb +1 -1
- metadata +5 -4
data/doc/apes02.html
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<html><head>
|
2
2
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
3
|
-
<title>Object Life Cycles and Garbage Collection</title><meta name="generator" content="DocBook XSL Stylesheets V1.
|
3
|
+
<title>Object Life Cycles and Garbage Collection</title><link rel="stylesheet" href="style.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.68.1"><link rel="start" href="book.html" title="Developing Graphical User Interfaces with FXRuby"><link rel="up" href="implementation.html" title="Appendix E. Implementation"><link rel="prev" href="implementation.html" title="Appendix E. Implementation"><link rel="next" href="apes03.html" title="Virtual Functions"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Object Life Cycles and Garbage Collection</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="implementation.html">Prev</a> </td><th width="60%" align="center">Appendix E. Implementation</th><td width="20%" align="right"> <a accesskey="n" href="apes03.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4915"></a>Object Life Cycles and Garbage Collection</h2></div></div></div><p>One of the more difficult issues to deal with was understanding
|
4
4
|
the "life cycle" of FOX objects (that is, the actual C++ objects) and
|
5
5
|
their relationship to the associated Ruby instances. Understanding this
|
6
6
|
relationship is critical when dealing with Ruby's garbage collector,
|
@@ -8,14 +8,14 @@
|
|
8
8
|
program into two groups, those objects that Ruby "owns" and those that
|
9
9
|
it doesn't. The first group (the "owned" objects) includes those that you
|
10
10
|
create explicitly from Ruby code. This is usually done by calling a class'
|
11
|
-
<
|
12
|
-
myButton = FXButton.new(parentWin, "Hello, World!", myIcon)</pre
|
11
|
+
<code class="methodname">new</code> method, e.g.</p><pre class="programlisting">myIcon = FXPNGIcon.new(myApp, File.open("icon.png", "rb").read)
|
12
|
+
myButton = FXButton.new(parentWin, "Hello, World!", myIcon)</pre><p>It's important to keep in mind that when you create an object like
|
13
13
|
this you're not only creating the Ruby instance part (i.e. whatever
|
14
14
|
overhead is usually associated with a Ruby instance) but a C++ FOX object
|
15
15
|
as well. Because we created these objects, we would reasonably expect them
|
16
16
|
to be destroyed when they are garbage-collected so that our programs
|
17
17
|
don't leak memory.</p><p>The other group of objects (those not owned by Ruby) are those
|
18
18
|
returned from most class instance methods; they are references to already-
|
19
|
-
existing objects. For example, <
|
20
|
-
</
|
21
|
-
instance.</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="
|
19
|
+
existing objects. For example, <code class="methodname">FXStatusBar#statusline
|
20
|
+
</code> returns a reference to the status bar's enclosed status line
|
21
|
+
instance.</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4934"></a>GL Objects</h3></div></div></div><p>A C++ <code class="classname">FXGLGroup</code> object owns all of the <code class="classname">FXGLObject</code> objects it "contains". In other words, when that <code class="classname">FXGLGroup</code> object is destroyed, it will also destroy all of the <code class="classname">FXGLObject</code> objects for which it holds pointers.</p><p>In order to keep track of <span class="emphasis"><em>which</em></span> GL objects have been added to an <code class="classname">FXGLGroup</code>, all of the FXRuby C++ classes derived from <code class="classname">FXGLObject</code> have a boolean member variable <em class="structfield"><code>owned</code></em> that indicates whether this object is "owned" or not. Until an <code class="classname">FXGLObject</code> object is added to a group, this member variable should stay false.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="implementation.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="implementation.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="apes03.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Appendix E. Implementation </td><td width="20%" align="center"><a accesskey="h" href="book.html">Home</a></td><td width="40%" align="right" valign="top"> Virtual Functions</td></tr></table></div></body></html>
|
data/doc/apes03.html
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
<html><head>
|
2
2
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
3
|
-
<title>Virtual Functions</title><meta name="generator" content="DocBook XSL Stylesheets V1.
|
3
|
+
<title>Virtual Functions</title><link rel="stylesheet" href="style.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.68.1"><link rel="start" href="book.html" title="Developing Graphical User Interfaces with FXRuby"><link rel="up" href="implementation.html" title="Appendix E. Implementation"><link rel="prev" href="apes02.html" title="Object Life Cycles and Garbage Collection"><link rel="next" href="cvs.html" title="Appendix F. Getting the Sources from CVS"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Virtual Functions</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="apes02.html">Prev</a> </td><th width="60%" align="center">Appendix E. Implementation</th><td width="20%" align="right"> <a accesskey="n" href="cvs.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4968"></a>Virtual Functions</h2></div></div></div><p>
|
4
4
|
One of the design requirements for FXRuby was to ensure that any
|
5
5
|
virtual function call made on a FOX object (from the C++ library
|
6
6
|
layer) is routed to the proper Ruby instance method, even if that
|
7
7
|
method has been overridden in a derived class.
|
8
8
|
</p><p>
|
9
9
|
For example, many of the FXRuby example programs are structured with a
|
10
|
-
main window class that subclasses <
|
11
|
-
and then overrides its <
|
10
|
+
main window class that subclasses <code class="classname">FXMainWindow</code>
|
11
|
+
and then overrides its <code class="methodname">create</code> instance method:</p><pre class="programlisting">class MyMainWindow < Fox::FXMainWindow
|
12
12
|
# overrides the base class version, FXMainWindow#create
|
13
13
|
def create
|
14
14
|
end
|
15
|
-
end</pre
|
15
|
+
end</pre><p>This <code class="methodname">create</code> method isn't called directly from Ruby code, however; it's called as a side effect of calling <code class="methodname">FXApp#create</code>. Inside the C++ FOX library, the <code class="methodname">FXApp::create()</code> member function recursively calls <code class="methodname">create()</code> on all of the application's windows and eventually calls the virtual <code class="methodname">FXMainWindow::create()</code> member function as well:
|
16
16
|
</p><div class="screenshot"><div class="mediaobject" align="center"><img src="images/call-chain-example.png" align="middle"></div></div><p>
|
17
|
-
To ensure that our main window's overridden <
|
18
|
-
</
|
17
|
+
To ensure that our main window's overridden <code class="methodname">create
|
18
|
+
</code> method is invoked instead of the base class implementation,
|
19
19
|
we need some special machinery in place.
|
20
20
|
</p><p>
|
21
21
|
For every C++ class that declares virtual member functions, we derive
|
22
22
|
a new C++ class that overrides all of those virtual functions with special
|
23
23
|
stubs that know how to make method calls on Ruby instances. The naming
|
24
24
|
convention for these classes is that the "FX" prefix is replaced with
|
25
|
-
"FXRb"; for example, our <
|
26
|
-
derived from FOX's <
|
25
|
+
"FXRb"; for example, our <code class="classname">FXRbButton</code> C++ class is
|
26
|
+
derived from FOX's <code class="classname">FXButton</code>:
|
27
27
|
</p><div class="screenshot"><div class="mediaobject" align="center"><img src="images/inheritance.png" align="middle"></div></div><p>
|
28
28
|
Although the implementation of these "stubs" varies from function to function, the
|
29
29
|
basic requirements are always the same:
|
30
30
|
</p><div class="orderedlist"><ol type="1"><li><p>Look up the Ruby object associated with this C++ object.</p></li><li><p>Convert each of the function's arguments to their Ruby
|
31
31
|
representation. For example, arguments of type <span class="type">FXint</span> are
|
32
|
-
converted to Ruby <
|
33
|
-
rb_funcall()</
|
32
|
+
converted to Ruby <code class="classname">Fixnum</code>s.</p></li><li><p>Call the Ruby object's method, using the <code class="function">
|
33
|
+
rb_funcall()</code> function from Ruby's C API, and capture its
|
34
34
|
result (which is itself a Ruby object).</p></li><li><p>Convert the method call's result back to the virtual
|
35
35
|
function's C++ return type, and then return that result from the C++
|
36
36
|
function. For example, if the C++ function has a <span class="type"> FXbool</span>
|
37
37
|
return type, we would expect the corresponding Ruby method to return
|
38
|
-
either <
|
38
|
+
either <code class="constant">Qtrue</code> or <code class="constant">Qfalse</code>.</p></li></ol></div><p>
|
39
39
|
</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="apes02.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="implementation.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="cvs.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Object Life Cycles and Garbage Collection </td><td width="20%" align="center"><a accesskey="h" href="book.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix F. Getting the Sources from CVS</td></tr></table></div></body></html>
|
data/doc/book.html
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
<html><head>
|
2
2
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
3
|
-
<title>Developing Graphical User Interfaces with FXRuby</title><meta name="generator" content="DocBook XSL Stylesheets V1.
|
3
|
+
<title>Developing Graphical User Interfaces with FXRuby</title><link rel="stylesheet" href="style.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.68.1"><link rel="start" href="book.html" title="Developing Graphical User Interfaces with FXRuby"><link rel="next" href="pt01.html" title="Part I. The Basics"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Developing Graphical User Interfaces with FXRuby</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="pt01.html">Next</a></td></tr></table><hr></div><div class="book" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="book"></a>Developing Graphical User Interfaces with FXRuby</h1></div><div><h2 class="subtitle">Covers FXRuby Version 1.6</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Lyle</span> <span class="surname">Johnson</span></h3></div></div><div><p class="copyright">Copyright © 2006 J. Lyle Johnson</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="part"><a href="pt01.html">I. The Basics</a></span></dt><dd><dl><dt><span class="preface"><a href="goals.html">History and Goals</a></span></dt><dt><span class="chapter"><a href="build.html">1. Building from Source Code</a></span></dt><dt><span class="chapter"><a href="gems.html">2. Installing from Gems</a></span></dt><dt><span class="chapter"><a href="tutorial1.html">3. Hello, World!</a></span></dt><dd><dl><dt><span class="section"><a href="tutorial1.html#d0e597">First Things First</a></span></dt><dt><span class="section"><a href="ch03s02.html">Better living through buttons</a></span></dt><dt><span class="section"><a href="ch03s03.html">Messages</a></span></dt><dt><span class="section"><a href="ch03s04.html">Adding a tool tip</a></span></dt><dt><span class="section"><a href="ch03s05.html">Adding an icon</a></span></dt></dl></dd><dt><span class="chapter"><a href="clipboardtut.html">4. Working With the Clipboard</a></span></dt><dd><dl><dt><span class="section"><a href="clipboardtut.html#d0e986">Basic Application</a></span></dt><dt><span class="section"><a href="ch04s02.html">Acquiring the Clipboard</a></span></dt><dt><span class="section"><a href="ch04s03.html">Sending Data to the Clipboard</a></span></dt><dt><span class="section"><a href="ch04s04.html">Pasting Data from the Clipboard</a></span></dt></dl></dd><dt><span class="chapter"><a href="dragdroptut.html">5. Drag and Drop</a></span></dt><dd><dl><dt><span class="section"><a href="dragdroptut.html#d0e1201">Drop Sites</a></span></dt><dt><span class="section"><a href="ch05s02.html">Drag Sources</a></span></dt><dt><span class="section"><a href="ch05s03.html">Putting It All Together</a></span></dt></dl></dd><dt><span class="chapter"><a href="unicode.html">6. Unicode and FXRuby</a></span></dt><dd><dl><dt><span class="section"><a href="unicode.html#d0e1608">Basic Application</a></span></dt></dl></dd><dt><span class="chapter"><a href="examples.html">7. Examples</a></span></dt><dt><span class="chapter"><a href="events.html">8. FXRuby's Message-Target System</a></span></dt><dt><span class="chapter"><a href="todo.html">9. To-do list</a></span></dt><dt><span class="chapter"><a href="infosources.html">10. Other Sources of Information</a></span></dt><dt><span class="chapter"><a href="changes.html">11. Change History</a></span></dt></dl></dd><dt><span class="part"><a href="pt02.html">II. Appendices</a></span></dt><dd><dl><dt><span class="appendix"><a href="opengl.html">A. Using OpenGL with FXRuby</a></span></dt><dt><span class="appendix"><a href="scintilla.html">B. Using Scintilla with FXRuby</a></span></dt><dt><span class="appendix"><a href="differences.html">C. Differences between FOX and FXRuby</a></span></dt><dt><span class="appendix"><a href="library.html">D. The FXRuby Standard Library</a></span></dt><dt><span class="appendix"><a href="implementation.html">E. Implementation</a></span></dt><dd><dl><dt><span class="section"><a href="implementation.html#d0e4896">Code Generation</a></span></dt><dt><span class="section"><a href="apes02.html">Object Life Cycles and Garbage Collection</a></span></dt><dd><dl><dt><span class="section"><a href="apes02.html#d0e4934">GL Objects</a></span></dt></dl></dd><dt><span class="section"><a href="apes03.html">Virtual Functions</a></span></dt></dl></dd><dt><span class="appendix"><a href="cvs.html">F. Getting the Sources from CVS</a></span></dt></dl></dd></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="pt01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"> </td><td width="40%" align="right" valign="top"> Part I. The Basics</td></tr></table></div></body></html>
|
data/doc/build.html
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<html><head>
|
2
2
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
3
|
-
<title>Chapter 1. Building from Source Code</title><meta name="generator" content="DocBook XSL Stylesheets V1.
|
3
|
+
<title>Chapter 1. Building from Source Code</title><link rel="stylesheet" href="style.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.68.1"><link rel="start" href="book.html" title="Developing Graphical User Interfaces with FXRuby"><link rel="up" href="pt01.html" title="Part I. The Basics"><link rel="prev" href="goals.html" title="History and Goals"><link rel="next" href="gems.html" title="Chapter 2. Installing from Gems"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 1. Building from Source Code</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="goals.html">Prev</a> </td><th width="60%" align="center">Part I. The Basics</th><td width="20%" align="right"> <a accesskey="n" href="gems.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="build"></a>Chapter 1. Building from Source Code</h2></div></div></div><p>A few words of advice, before getting started:</p><div class="itemizedlist"><ul type="bullet"><li style="list-style-type: disc"><p>If you're planning to use FXRuby on Windows, with the standard
|
4
4
|
<a href="http://rubyinstaller.rubyforge.org" target="_top">Ruby Installer for
|
5
5
|
Windows</a>, you may wish to just download the pre-compiled binaries
|
6
6
|
from the <a href="http://rubyforge.org/projects/fxruby" target="_top">RubyForge
|
@@ -8,126 +8,126 @@
|
|
8
8
|
consult <a href="http://www.fox-toolkit.net/cgi-bin/wiki.pl?Mac_OS_X" target="_top">this
|
9
9
|
page</a> from the <a href="http://www.fox-toolkit.net" target="_top">FOX
|
10
10
|
Community Wiki</a>, in addition to the standard build instructions
|
11
|
-
listed below.</p></li></ul></div><div class="simplesect" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e92"></a>Building From Source on Unix/Linux</h2></div></div
|
11
|
+
listed below.</p></li></ul></div><div class="simplesect" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e92"></a>Building From Source on Unix/Linux</h2></div></div></div><p>These instructions assume that you've already downloaded, compiled
|
12
12
|
and installed FOX. Next, you'll need to download the FXRuby source code
|
13
|
-
tarball and unpack it by typing:</p><
|
14
|
-
directory and configure the build by typing:</p><
|
15
|
-
the FOX include files and library in the standard <
|
13
|
+
tarball and unpack it by typing:</p><pre class="screen">$ <span><strong class="command">tar xzf FXRuby-1.6.0.tar.gz</strong></span></pre><p>This will create a new directory called <code class="filename">FXRuby-1.6.0</code>. Change to the top-level
|
14
|
+
directory and configure the build by typing:</p><pre class="screen">$ <span><strong class="command">ruby install.rb config</strong></span></pre><p>By default, the <code class="filename">install.rb</code> script will look for
|
15
|
+
the FOX include files and library in the standard <code class="filename">/usr/local/include/fox-1.6</code> and <code class="filename">/usr/local/lib</code> directories, respectively. You
|
16
16
|
can override these locations by passing a few additional arguments to
|
17
|
-
<
|
17
|
+
<code class="filename">install.rb</code> during this step, e.g.</p><pre class="screen">$ <span><strong class="command">ruby install.rb config -- \
|
18
18
|
--with-fox-include=/home/lyle/fox-1.6.3/include \
|
19
|
-
--with-fox-lib=/home/lyle/fox-1.6.3/src/.libs</
|
20
|
-
typing:</p><
|
19
|
+
--with-fox-lib=/home/lyle/fox-1.6.3/src/.libs</strong></span></pre><p>Once the build has been configured, you can start the build by
|
20
|
+
typing:</p><pre class="screen">$ <span><strong class="command">ruby install.rb setup</strong></span></pre><p>It will take quite awhile to build FXRuby, even on a fast machine,
|
21
21
|
so this might be a good time to take a coffee break. If you run into
|
22
22
|
problems during the compilation, please check the <a href="build.html#tragedies" title="Things That Can Go Wrong">list of things that can go wrong</a> for
|
23
|
-
workarounds for those problems.</p><p>Once it's finished compiling, install FXRuby by typing:</p><
|
24
|
-
probably fire up <
|
25
|
-
irb(main):001:0> <
|
23
|
+
workarounds for those problems.</p><p>Once it's finished compiling, install FXRuby by typing:</p><pre class="screen">$ <span><strong class="command">ruby install.rb install</strong></span></pre><p>As a quick sanity check, to make sure that all is well, you should
|
24
|
+
probably fire up <code class="filename">irb</code> and try to import FXRuby:</p><pre class="screen">$ <span><strong class="command">irb</strong></span>
|
25
|
+
irb(main):001:0> <strong class="userinput"><code>require 'fox'</code></strong>
|
26
26
|
true
|
27
|
-
irb(main):002:0></pre
|
27
|
+
irb(main):002:0></pre><p>If the import failed (usually with a message along the lines of
|
28
28
|
"Cannot load library"), check the <a href="build.html#tragedies" title="Things That Can Go Wrong">list of things
|
29
29
|
that can go wrong</a> for known problems. If that still doesn't solve
|
30
30
|
your problem, drop me an e-mail or ask around on the Ruby newsgroup or
|
31
31
|
mailing list; it's quite likely that someone else has run into this
|
32
32
|
problem too. Once you do have a working FXRuby installation, you're ready
|
33
|
-
to check out the example programs.</p></div><div class="simplesect" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e163"></a>Building From Source on Windows (Using Visual C++)</h2></div></div
|
33
|
+
to check out the example programs.</p></div><div class="simplesect" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e163"></a>Building From Source on Windows (Using Visual C++)</h2></div></div></div><p>This section describes how to compile FXRuby using Microsoft Visual
|
34
34
|
C++, for use with a Ruby that was also compiled using Visual C++.</p><p>This discussion assumes that you've built Ruby using the
|
35
35
|
instructions and build files distributed with the standard Ruby source
|
36
36
|
code. To review, you should have started by unpacking the source code
|
37
|
-
tarball, changing into the top-level source code directory (e.g. <
|
37
|
+
tarball, changing into the top-level source code directory (e.g. <code class="filename">C:\ruby-1.8.4</code>) and then typing:</p><pre class="screen">C:\ruby-1.8.4><span><strong class="command">win32\configure</strong></span>
|
38
38
|
type 'nmake' to make ruby for mswin32.
|
39
|
-
C:\ruby-1.8.4><
|
40
|
-
typing, e.g.,</p><
|
39
|
+
C:\ruby-1.8.4><span><strong class="command">nmake</strong></span></pre><p>After the compilation finished, you installed Ruby somewhere by
|
40
|
+
typing, e.g.,</p><pre class="screen">C:\ruby-1.8.4><span><strong class="command">nmake DESTDIR=C:\ruby install</strong></span></pre><p>Similarly, I'm assuming that you built the FOX library using the
|
41
41
|
Developer Studio project files distributed with the standard FOX source
|
42
|
-
code distribution.</p><p>Now you can configure the FXRuby build by typing:</p><
|
42
|
+
code distribution.</p><p>Now you can configure the FXRuby build by typing:</p><pre class="screen">C:\FXRuby-1.6.0><span><strong class="command">ruby install.rb config --make-prog=nmake -- \
|
43
43
|
--with-fox-include=C:\fox-1.6.3\include \
|
44
|
-
--with-fox-lib=C:\fox-1.6.3\lib</
|
45
|
-
typing:</p><
|
44
|
+
--with-fox-lib=C:\fox-1.6.3\lib</strong></span></pre><p>Once the build has been configured, you can start the build by
|
45
|
+
typing:</p><pre class="screen">C:\FXRuby-1.6.0> <span><strong class="command">ruby install.rb setup</strong></span></pre><p>It will take quite awhile to build FXRuby, even on a fast machine,
|
46
46
|
so this might be a good time to take a coffee break. Because Visual C++ is
|
47
47
|
such a strict compiler (usually a good thing), you will probably run into
|
48
48
|
a few problems with non-ANSI declarations in the Ruby header files. If you
|
49
49
|
do run into problems during the compilation, just check the next section
|
50
50
|
for a list of things that could go wrong, and workarounds for those
|
51
51
|
problems. None of them are showstoppers and none require you to restart
|
52
|
-
the compile from scratch (just type <
|
53
|
-
setup</
|
54
|
-
probably fire up <
|
55
|
-
irb(main):001:0> <
|
52
|
+
the compile from scratch (just type <span><strong class="command">ruby install.rb
|
53
|
+
setup</strong></span> to pick up where you left off).</p><p>Once it's finished compiling, install FXRuby by typing:</p><pre class="screen">C:\FXRuby-1.6.0> <span><strong class="command">ruby install.rb install</strong></span></pre><p>As a quick sanity check, to make sure that all is well, you should
|
54
|
+
probably fire up <code class="filename">irb</code> and try to import FXRuby:</p><pre class="screen">C:\FXRuby-1.6.0> <span><strong class="command">irb</strong></span>
|
55
|
+
irb(main):001:0> <strong class="userinput"><code>require 'fox16'</code></strong>
|
56
56
|
true
|
57
|
-
irb(main):002:0></pre
|
57
|
+
irb(main):002:0></pre><p>If the import failed (usually with a message along the lines of
|
58
58
|
"Cannot load library"), check the list of things that can go wrong for
|
59
59
|
known problems. If that still doesn't solve your problem, drop me an
|
60
60
|
e-mail or ask around on the Ruby newsgroup or mailing list; it's quite
|
61
61
|
likely that someone else has run into this problem too. Once you do have a
|
62
62
|
working FXRuby installation, you're ready to check out the example
|
63
|
-
programs.</p></div><div class="simplesect" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tragedies"></a>Things That Can Go Wrong</h2></div></div
|
63
|
+
programs.</p></div><div class="simplesect" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tragedies"></a>Things That Can Go Wrong</h2></div></div></div><p><span class="emphasis"><em>"Too many arguments to function..."</em></span></p><p>The include files for Ruby versions 1.6.7 and earlier still have
|
64
64
|
several function prototypes in the older "K & R" C style, where the
|
65
65
|
function's argument list is not included; for example, the function
|
66
|
-
<
|
66
|
+
<code class="function">rb_thread_wait_for()</code> takes a single argument of type
|
67
67
|
<span class="type">struct timeval</span>, but its prototype in
|
68
|
-
<
|
68
|
+
<code class="filename">intern.h</code> is:</p><pre class="programlisting">void rb_thread_wait_for();</pre><p>Because FXRuby is written in C++, and C++ requires strict ANSI
|
69
69
|
C-style function prototypes, code that attempts to call one of these
|
70
70
|
functions will fail to compile under some compilers. For example, the
|
71
|
-
error message from gcc will look something like this:</p><
|
71
|
+
error message from gcc will look something like this:</p><pre class="screen">FXRbApp.cpp: In method `long int FXRbApp::onChoreThreads (FXObject *, unsigned int, void *)':
|
72
72
|
/usr/local/lib/ruby/1.8/i686-linux/intern.h:172: too many arguments to function `void rb_thread_wait_for ()'
|
73
73
|
FXRbApp.cpp:100: at this point in file
|
74
|
-
make: *** [FXRbApp.o] Error 1</pre
|
75
|
-
something like this:</p><
|
74
|
+
make: *** [FXRbApp.o] Error 1</pre><p>while the error message from Microsoft's Visual C++ compiler looks
|
75
|
+
something like this:</p><pre class="screen">FXRbApp.cpp(109): error C2660: 'rb_thread_wait_for' : function does not take 1 parameters
|
76
76
|
NMAKE : fatal error U1077: 'cl' : return code '0x2'
|
77
|
-
Stop.</pre
|
77
|
+
Stop.</pre><p>This problem with the Ruby header files has been corrected for Ruby
|
78
78
|
versions 1.6.8 (and later), but if you're building for an older version of
|
79
79
|
Ruby you can do one of two things to work around the problem:</p><div class="itemizedlist"><ul type="bullet"><li style="list-style-type: disc"><p>If you're using gcc version 2.95 or earlier, try modifying the
|
80
|
-
compiler flags (<
|
81
|
-
<
|
82
|
-
<
|
80
|
+
compiler flags (<code class="constant">CFLAGS</code>) in the FXRuby
|
81
|
+
<code class="filename">Makefile</code> to include the
|
82
|
+
<code class="option">-fno-strict-prototype</code> option; this should instruct
|
83
83
|
the compiler to allow these kinds of discrepancies. Unfortunately,
|
84
84
|
this flag is not supported in more recent versions of gcc.</p></li><li style="list-style-type: disc"><p>A more direct approach is to just fix the offending declarations
|
85
85
|
in the Ruby include file(s), i.e. change the declaration for
|
86
|
-
<
|
87
|
-
<
|
88
|
-
in <
|
86
|
+
<code class="function">rb_thread_wait_for()</code> in
|
87
|
+
<code class="filename">intern.h</code> to read:</p><pre class="programlisting">void rb_thread_wait_for(struct timeval);</pre><p>and change the declaration for <code class="function">rb_gc_mark()</code>
|
88
|
+
in <code class="filename">intern.h</code> to read:</p><pre class="programlisting">void rb_gc_mark(VALUE);</pre></li></ul></div><p><span class="emphasis"><em>"Virtual Memory Exhausted"</em></span></p><p>For FXRuby releases earlier than version 0.99.173 it was common for
|
89
89
|
the compiler to run out of memory trying to compile
|
90
|
-
<
|
91
|
-
core_wrap.cpp:108596: virtual memory exhausted</pre
|
90
|
+
<code class="filename">core_wrap.cpp</code>, with an error message like:</p><pre class="screen">core_wrap.cpp: In function 'void Init_core()':
|
91
|
+
core_wrap.cpp:108596: virtual memory exhausted</pre><p>This failure was due to the use of optimizations by the compiler;
|
92
92
|
the FXRuby source code makes heavy use of C++ templates and some versions
|
93
93
|
of gcc require a lot of memory to process these. Starting with FXRuby
|
94
|
-
version 0.99.173, the <
|
94
|
+
version 0.99.173, the <code class="filename">extconf.rb</code> script
|
95
95
|
<span class="emphasis"><em>should</em></span> disable compiler optimizations when it
|
96
|
-
generates the FXRuby <
|
96
|
+
generates the FXRuby <code class="filename">Makefile</code>. If you suspect that
|
97
97
|
it's not disabling optimizations (or can see this by watching the compile
|
98
98
|
command lines), try modifying the compiler flags
|
99
|
-
(<
|
99
|
+
(<code class="constant">CFLAGS</code>) in the <code class="filename">Makefile</code> by hand
|
100
100
|
to do so.</p><p><span class="emphasis"><em>"Cannot load library"</em></span></p><p>On Linux and other Unix systems that support shared libraries, FOX
|
101
101
|
is typically installed as a shared library named
|
102
|
-
<
|
102
|
+
<code class="filename">libFOX-1.4.so</code>. After all of the source files for
|
103
103
|
FXRuby are compiled, the last step is to link all of the FXRuby object
|
104
104
|
files together with the FOX library (and possibly other system libraries)
|
105
|
-
to produce a new shared library, named <
|
105
|
+
to produce a new shared library, named <code class="filename">fox14.so</code>, that
|
106
106
|
Ruby can import as an extension module.</p><p>There are a few things that can go wrong when you try to import this
|
107
107
|
extension into Ruby. A common problem is that the operating system cannot
|
108
|
-
locate the FOX shared library (<
|
108
|
+
locate the FOX shared library (<code class="filename">libFOX-1.4.so</code>) when it
|
109
109
|
tries to dynamically load the FXRuby extension module; when this happens,
|
110
|
-
the error message will look something like:</p><
|
111
|
-
irb(main):001:0> <
|
110
|
+
the error message will look something like:</p><pre class="screen">$ <span><strong class="command">irb</strong></span>
|
111
|
+
irb(main):001:0> <strong class="userinput"><code>require 'fox'</code></strong>
|
112
112
|
LoadError: libFOX-0.99.so.173: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/1.6/i586-linux/fox.so
|
113
113
|
from (irb):1:in 'require'
|
114
114
|
from (irb):1
|
115
|
-
</pre
|
116
|
-
<
|
117
|
-
directory where <
|
118
|
-
if <
|
119
|
-
$ <
|
120
|
-
irb(main):001:0> <
|
121
|
-
</pre
|
122
|
-
<
|
115
|
+
</pre><p>One workaround for this problem is to modify the
|
116
|
+
<code class="constant">LD_LIBRARY_PATH</code> environment variable to include the
|
117
|
+
directory where <code class="filename">libFOX.so</code> is installed. For example,
|
118
|
+
if <code class="filename">libFOX-1.4.so</code> is installed in <code class="filename">/usr/local/lib</code>, try setting:</p><pre class="screen">$ <span><strong class="command">export LD_LIBRARY_PATH=/usr/local/lib</strong></span>
|
119
|
+
$ <span><strong class="command">irb</strong></span>
|
120
|
+
irb(main):001:0> <strong class="userinput"><code>require 'fox'</code></strong>
|
121
|
+
</pre><p>If this works, you can of course permanently add the
|
122
|
+
<code class="constant">LD_LIBRARY_PATH</code> setting to your login file(s) so that
|
123
123
|
you don't have to remember to type it each time. Another approach that
|
124
124
|
should work for Linux is to modify your
|
125
|
-
<
|
126
|
-
directory (e.g. <
|
127
|
-
this instead, you'll need to (as root):</p><div class="orderedlist"><ol type="1" compact><li><p>Edit your <
|
128
|
-
directory where <
|
129
|
-
and,</p></li><li><p>At the shell prompt, type <
|
125
|
+
<code class="filename">/etc/ld.so.conf</code> file to include the installation
|
126
|
+
directory (e.g. <code class="filename">/usr/local/lib</code>). If you'd like to do
|
127
|
+
this instead, you'll need to (as root):</p><div class="orderedlist"><ol type="1" compact><li><p>Edit your <code class="filename">/etc/ld.so.conf</code> file and add the
|
128
|
+
directory where <code class="filename">libFOX.so</code> is installed;
|
129
|
+
and,</p></li><li><p>At the shell prompt, type <span><strong class="command">ldconfig</strong></span> to reload
|
130
130
|
the linker configuration.</p></li></ol></div><p><span class="emphasis"><em>"Undefined symbol..."</em></span></p><p>Another problem that has been reported by users of both Debian
|
131
|
-
GNU/Linux and NetBSD 1.5 is an error message along the lines of:</p><
|
132
|
-
<
|
133
|
-
<
|
131
|
+
GNU/Linux and NetBSD 1.5 is an error message along the lines of:</p><pre class="screen">/usr/lib/libstdc++.so.2: Undefined symbol "__vt_9exception"...</pre><p>The fix for this problem is reported to be to modify the FXRuby
|
132
|
+
<code class="filename">Makefile</code> and add <code class="option">-lgcc</code> to the
|
133
|
+
<code class="constant">LIBS</code> line.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="goals.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="pt01.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="gems.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">History and Goals </td><td width="20%" align="center"><a accesskey="h" href="book.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 2. Installing from Gems</td></tr></table></div></body></html>
|
data/doc/ch03s02.html
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
<html><head>
|
2
2
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
3
|
-
<title>Better living through buttons</title><meta name="generator" content="DocBook XSL Stylesheets V1.
|
3
|
+
<title>Better living through buttons</title><link rel="stylesheet" href="style.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.68.1"><link rel="start" href="book.html" title="Developing Graphical User Interfaces with FXRuby"><link rel="up" href="tutorial1.html" title="Chapter 3. Hello, World!"><link rel="prev" href="tutorial1.html" title="Chapter 3. Hello, World!"><link rel="next" href="ch03s03.html" title="Messages"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Better living through buttons</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="tutorial1.html">Prev</a> </td><th width="60%" align="center">Chapter 3. Hello, World!</th><td width="20%" align="right"> <a accesskey="n" href="ch03s03.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e724"></a>Better living through buttons</h2></div></div></div><p>Obviously, we need to add a few things to make it more interesting.
|
4
4
|
Let's start by putting a button inside the main window. The
|
5
|
-
<
|
6
|
-
widget:</p><
|
5
|
+
<code class="classname">FXButton</code> class provides a standard push-button
|
6
|
+
widget:</p><pre class="programlisting">require 'fox16'
|
7
7
|
|
8
8
|
include Fox
|
9
9
|
|
10
10
|
theApp = FXApp.new
|
11
11
|
|
12
12
|
theMainWindow = FXMainWindow.new(theApp, "Hello")
|
13
|
-
<span class="bold"><
|
13
|
+
<span class="bold"><strong>FXButton.new(theMainWindow, "Hello, World!")</strong></span>
|
14
14
|
theApp.create
|
15
15
|
|
16
16
|
theMainWindow.show
|
17
17
|
|
18
|
-
theApp.run</pre
|
19
|
-
the first argument to <
|
18
|
+
theApp.run</pre><p>As you might guess, passing <em class="parameter"><code>theMainWindow</code></em> as
|
19
|
+
the first argument to <code class="methodname">FXButton.new</code> tells FXRuby
|
20
20
|
that the new button is a child of the main window. The second argument to
|
21
|
-
<
|
21
|
+
<code class="methodname">FXButton.new</code> is a string that will be displayed
|
22
22
|
on the button. If you run the program <span class="emphasis"><em>now</em></span>, you should
|
23
23
|
see this:</p><div class="screenshot"><div class="mediaobject" align="center"><img src="images/hello-with-button.png" align="middle"></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="tutorial1.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="tutorial1.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch03s03.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 3. Hello, World! </td><td width="20%" align="center"><a accesskey="h" href="book.html">Home</a></td><td width="40%" align="right" valign="top"> Messages</td></tr></table></div></body></html>
|
data/doc/ch03s03.html
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
<html><head>
|
2
2
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
3
|
-
<title>Messages</title><meta name="generator" content="DocBook XSL Stylesheets V1.
|
3
|
+
<title>Messages</title><link rel="stylesheet" href="style.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.68.1"><link rel="start" href="book.html" title="Developing Graphical User Interfaces with FXRuby"><link rel="up" href="tutorial1.html" title="Chapter 3. Hello, World!"><link rel="prev" href="ch03s02.html" title="Better living through buttons"><link rel="next" href="ch03s04.html" title="Adding a tool tip"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Messages</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch03s02.html">Prev</a> </td><th width="60%" align="center">Chapter 3. Hello, World!</th><td width="20%" align="right"> <a accesskey="n" href="ch03s04.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e755"></a>Messages</h2></div></div></div><p>Now we're cookin' with Crisco, but let's press on and see what other
|
4
4
|
things we can do to improve this. You may have noticed by now that the
|
5
5
|
only way to quit the program is to close the window using the window
|
6
6
|
manager's "close window" option, or to just kill the program outright. We
|
7
7
|
can do better than that. Let's add a message handler for the
|
8
|
-
<
|
9
|
-
causes the program to exit:</p><
|
8
|
+
<code class="classname">FXButton</code> such that when you click the button, it
|
9
|
+
causes the program to exit:</p><pre class="programlisting">require 'fox16'
|
10
10
|
|
11
11
|
include Fox
|
12
12
|
|
@@ -14,39 +14,39 @@ theApp = FXApp.new
|
|
14
14
|
|
15
15
|
theMainWindow = FXMainWindow.new(theApp, "Hello")
|
16
16
|
theButton = FXButton.new(theMainWindow, "Hello, World!")
|
17
|
-
<span class="bold"><
|
17
|
+
<span class="bold"><strong>theButton.connect(SEL_COMMAND) do |sender, selector, data|
|
18
18
|
exit
|
19
|
-
end</
|
19
|
+
end</strong></span>
|
20
20
|
theApp.create
|
21
21
|
|
22
22
|
theMainWindow.show
|
23
23
|
|
24
|
-
theApp.run</pre
|
24
|
+
theApp.run</pre><p>Most FOX objects send out messages (also known as
|
25
25
|
<span class="emphasis"><em>events</em></span>) when something interesting happens. FOX
|
26
26
|
messages have four important elements:</p><div class="orderedlist"><ol type="1"><li><p>The message <span class="emphasis"><em>sender</em></span> is the object that sends
|
27
|
-
the message. In this case, the <
|
27
|
+
the message. In this case, the <code class="classname">FXButton</code>
|
28
28
|
instance is the sender.</p></li><li><p>The message <span class="emphasis"><em>type</em></span> is a predefined integer
|
29
29
|
constant that indicates what kind of event has occurred (i.e. why this
|
30
30
|
message is being sent). In this case, the message type is
|
31
|
-
<
|
31
|
+
<code class="constant">SEL_COMMAND</code>, which indicates that the command
|
32
32
|
associated with this widget should be invoked.</p></li><li><p>The message <span class="emphasis"><em>identifier</em></span> is another integer
|
33
33
|
constant that is used to distinguish between different messages of the
|
34
34
|
same type. For example, the message that tells a FOX window to make
|
35
|
-
itself visible is a <
|
36
|
-
identifier <
|
37
|
-
<
|
38
|
-
<
|
39
|
-
identifier, <
|
40
|
-
<
|
35
|
+
itself visible is a <code class="constant">SEL_COMMAND</code> message with the
|
36
|
+
identifier <code class="constant">FXWindow::ID_SHOW</code> (where
|
37
|
+
<code class="constant">ID_SHOW</code> is a constant defined in the
|
38
|
+
<code class="classname">FXWindow</code> class). A different message
|
39
|
+
identifier, <code class="constant">FXWindow::ID_HIDE</code>, tells an
|
40
|
+
<code class="classname">FXWindow</code> instance to make itself
|
41
41
|
invisible.</p></li><li><p>The message <span class="emphasis"><em>data</em></span> is an object containing
|
42
42
|
message-specific information. For this case (the
|
43
|
-
<
|
43
|
+
<code class="classname">FXButton</code>'s <code class="constant">SEL_COMMAND</code>
|
44
44
|
message, there is no interesting message data, but we'll see other
|
45
45
|
kinds of messages where the message data is useful.</p></li></ol></div><p>For historical reasons, the message type and identifier are usually
|
46
46
|
packed into a single 32-bit unsigned integer known as the
|
47
47
|
<span class="emphasis"><em>selector</em></span>, and this is the value that is passed into
|
48
48
|
the message handler block. Since we don't actually need to use the
|
49
|
-
<
|
50
|
-
<
|
51
|
-
we can just ignore them and shorten the code to:</p><
|
49
|
+
<em class="parameter"><code>sender</code></em>, <em class="parameter"><code>selector</code></em> or
|
50
|
+
<em class="parameter"><code>data</code></em> arguments for this particular message handler,
|
51
|
+
we can just ignore them and shorten the code to:</p><pre class="programlisting">theButton.connect(SEL_COMMAND) { exit }</pre><p>Re-run the program and push the button to convince yourself that it
|
52
52
|
works.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03s02.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="tutorial1.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch03s04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Better living through buttons </td><td width="20%" align="center"><a accesskey="h" href="book.html">Home</a></td><td width="40%" align="right" valign="top"> Adding a tool tip</td></tr></table></div></body></html>
|