summaryrefslogtreecommitdiff
path: root/libs/gtkmm2ext
diff options
context:
space:
mode:
Diffstat (limited to 'libs/gtkmm2ext')
-rw-r--r--libs/gtkmm2ext/.cvsignore5
-rw-r--r--libs/gtkmm2ext/AUTHORS2
-rw-r--r--libs/gtkmm2ext/COPYING340
-rw-r--r--libs/gtkmm2ext/ChangeLog0
-rw-r--r--libs/gtkmm2ext/NEWS0
-rw-r--r--libs/gtkmm2ext/README0
-rw-r--r--libs/gtkmm2ext/SConscript74
-rw-r--r--libs/gtkmm2ext/auto_spin.cc262
-rw-r--r--libs/gtkmm2ext/barcontroller.cc497
-rw-r--r--libs/gtkmm2ext/bindable_button.cc155
-rw-r--r--libs/gtkmm2ext/choice.cc97
-rw-r--r--libs/gtkmm2ext/click_box.cc125
-rw-r--r--libs/gtkmm2ext/controller.cc92
-rw-r--r--libs/gtkmm2ext/fastmeter.cc291
-rw-r--r--libs/gtkmm2ext/gettext.h82
-rw-r--r--libs/gtkmm2ext/gtk_ui.cc823
-rw-r--r--libs/gtkmm2ext/gtkmm2ext-config.in232
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/.cvsignore1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/auto_spin.h71
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/barcontroller.h113
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/bindable_button.h77
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/choice.h44
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/click_box.h61
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/controller.h59
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/doi.h37
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/fastmeter.h85
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/gtk_ui.h219
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/gtkutils.h30
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/hexentry.h59
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/idle_adjustment.h26
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/pix.h87
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/pixscroller.h47
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/popup.h57
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/prompter.h86
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/selector.h103
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/slider_controller.h98
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/stop_signal.h14
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/tearoff.h63
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/textviewer.h58
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/utils.h41
-rw-r--r--libs/gtkmm2ext/gtkutils.cc41
-rw-r--r--libs/gtkmm2ext/hexentry.cc111
-rw-r--r--libs/gtkmm2ext/i18n.h11
-rw-r--r--libs/gtkmm2ext/idle_adjustment.cc54
-rw-r--r--libs/gtkmm2ext/libgtkmm2ext.pc.in11
-rw-r--r--libs/gtkmm2ext/libgtkmm2ext.spec.in68
-rw-r--r--libs/gtkmm2ext/pix.cc231
-rw-r--r--libs/gtkmm2ext/pixscroller.cc248
-rw-r--r--libs/gtkmm2ext/po/el_GR.po79
-rw-r--r--libs/gtkmm2ext/po/es_ES.po78
-rw-r--r--libs/gtkmm2ext/po/pt_BR.po79
-rw-r--r--libs/gtkmm2ext/po/ru_RU.po78
-rw-r--r--libs/gtkmm2ext/popup.cc134
-rw-r--r--libs/gtkmm2ext/prompter.cc118
-rw-r--r--libs/gtkmm2ext/selector.cc238
-rw-r--r--libs/gtkmm2ext/slider_controller.cc183
-rw-r--r--libs/gtkmm2ext/tearoff.cc164
-rw-r--r--libs/gtkmm2ext/textviewer.cc127
-rw-r--r--libs/gtkmm2ext/utils.cc47
59 files changed, 6713 insertions, 0 deletions
diff --git a/libs/gtkmm2ext/.cvsignore b/libs/gtkmm2ext/.cvsignore
new file mode 100644
index 0000000000..c3ceb3bfd5
--- /dev/null
+++ b/libs/gtkmm2ext/.cvsignore
@@ -0,0 +1,5 @@
+libgtkmmext.pc
+libgtkmmext.spec
+version.cc
+*.mo
+*.pot
diff --git a/libs/gtkmm2ext/AUTHORS b/libs/gtkmm2ext/AUTHORS
new file mode 100644
index 0000000000..396f223e8c
--- /dev/null
+++ b/libs/gtkmm2ext/AUTHORS
@@ -0,0 +1,2 @@
+Written primarily by Paul Davis.
+Porting to gtkmm2 and sigc++2 work done by Taybin Rutkin.
diff --git a/libs/gtkmm2ext/COPYING b/libs/gtkmm2ext/COPYING
new file mode 100644
index 0000000000..d60c31a97a
--- /dev/null
+++ b/libs/gtkmm2ext/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/libs/gtkmm2ext/ChangeLog b/libs/gtkmm2ext/ChangeLog
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/gtkmm2ext/ChangeLog
diff --git a/libs/gtkmm2ext/NEWS b/libs/gtkmm2ext/NEWS
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/gtkmm2ext/NEWS
diff --git a/libs/gtkmm2ext/README b/libs/gtkmm2ext/README
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/gtkmm2ext/README
diff --git a/libs/gtkmm2ext/SConscript b/libs/gtkmm2ext/SConscript
new file mode 100644
index 0000000000..e3ba3f1fcd
--- /dev/null
+++ b/libs/gtkmm2ext/SConscript
@@ -0,0 +1,74 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+Import('env final_prefix install_prefix libraries i18n')
+
+gtkmm2ext = env.Copy()
+gtkmm2ext.Merge ([
+ libraries['sigc2'],
+ libraries['pbd3'],
+ libraries['midi++2'],
+ libraries['gtk2'],
+ libraries['glibmm2'],
+ libraries['pangomm'],
+ libraries['atkmm'],
+ libraries['gdkmm2'],
+ libraries['gtkmm2']
+ ])
+
+#
+# this defines the version number of libgtkmm2ext
+#
+
+domain = 'libgtkmm2ext'
+
+gtkmm2ext.Append(DOMAIN=domain,MAJOR=0,MINOR=8,MICRO=0)
+gtkmm2ext.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"")
+gtkmm2ext.Append(CCFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+gtkmm2ext.Append(PACKAGE=domain)
+gtkmm2ext.Append(POTFILE=domain + '.pot')
+
+gtkmm2ext_files = Split("""
+auto_spin.cc
+barcontroller.cc
+bindable_button.cc
+choice.cc
+click_box.cc
+controller.cc
+fastmeter.cc
+gtk_ui.cc
+gtkutils.cc
+hexentry.cc
+idle_adjustment.cc
+pix.cc
+pixscroller.cc
+popup.cc
+prompter.cc
+selector.cc
+slider_controller.cc
+tearoff.cc
+textviewer.cc
+utils.cc
+version.cc
+""")
+
+gtkmm2ext.VersionBuild(['version.cc','gtkmm2ext/version.h'], 'SConscript')
+
+gtkmm2ext.Append(CCFLAGS="-D_REENTRANT")
+gtkmm2ext.Append(CCFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+libgtkmm2ext = gtkmm2ext.StaticLibrary('gtkmm2ext', gtkmm2ext_files)
+
+Default(libgtkmm2ext)
+
+if env['NLS']:
+ i18n (gtkmm2ext, gtkmm2ext_files, env)
+
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+ [ 'SConscript', 'i18n.h', 'gettext.h'] +
+ gtkmm2ext_files +
+ glob.glob('po/*.po') +
+ glob.glob('gtkmm2ext/*.h')))
diff --git a/libs/gtkmm2ext/auto_spin.cc b/libs/gtkmm2ext/auto_spin.cc
new file mode 100644
index 0000000000..0830eca77e
--- /dev/null
+++ b/libs/gtkmm2ext/auto_spin.cc
@@ -0,0 +1,262 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtkmm2ext/auto_spin.h>
+#include <cmath>
+
+using namespace Gtkmm2ext;
+using namespace std;
+
+#define upper adjustment.get_upper()
+#define lower adjustment.get_lower()
+#define step_increment adjustment.get_step_increment()
+#define page_increment adjustment.get_page_increment()
+
+const unsigned int AutoSpin::initial_timer_interval = 500; /* msecs */
+const unsigned int AutoSpin::timer_interval = 20; /* msecs */
+const unsigned int AutoSpin::climb_timer_calls = 5; /* between climbing */
+
+AutoSpin::AutoSpin (Gtk::Adjustment &adjr, gfloat cr)
+ : adjustment (adjr),
+ climb_rate (cr)
+
+{
+ initial = adjustment.get_value();
+ left_is_decrement = true;
+ wrap = false;
+ have_timer = false;
+ need_timer = false;
+ timer_calls = 0;
+}
+
+void
+AutoSpin::stop_timer ()
+{
+ if (have_timer) {
+ gtk_timeout_remove (timeout_tag);
+ have_timer = false;
+ }
+}
+
+gint
+AutoSpin::stop_spinning (GdkEventButton *ev)
+{
+ need_timer = false;
+ stop_timer ();
+ return FALSE;
+}
+
+gint
+AutoSpin::button_press (GdkEventButton *ev)
+{
+ bool shifted = false;
+ bool control = false;
+ bool with_decrement = false;
+
+ stop_spinning (0);
+
+ if (ev->state & GDK_SHIFT_MASK) {
+ /* use page shift */
+
+ shifted = true;
+ }
+
+ if (ev->state & GDK_CONTROL_MASK) {
+ /* go to upper/lower bound on button1/button2 */
+
+ control = true;
+ }
+
+ /* XXX should figure out which button is left/right */
+
+ switch (ev->button) {
+ case 1:
+ if (control) {
+ set_value (left_is_decrement ? lower : upper);
+ return TRUE;
+ } else {
+ if (left_is_decrement) {
+ with_decrement = true;
+ } else {
+ with_decrement = false;
+ }
+ }
+ break;
+
+ case 2:
+ if (!control) {
+ set_value (initial);
+ }
+ return TRUE;
+ break;
+
+ case 3:
+ if (control) {
+ set_value (left_is_decrement ? upper : lower);
+ return TRUE;
+ }
+ break;
+
+ case 4:
+ if (!control) {
+ adjust_value (shifted ? page_increment : step_increment);
+ } else {
+ set_value (upper);
+ }
+ return TRUE;
+ break;
+
+ case 5:
+ if (!control) {
+ adjust_value (shifted ? -page_increment : -step_increment);
+ } else {
+ set_value (lower);
+ }
+ return TRUE;
+ break;
+ }
+
+ start_spinning (with_decrement, shifted);
+ return TRUE;
+}
+
+void
+AutoSpin::start_spinning (bool decrement, bool page)
+{
+ timer_increment = page ? page_increment : step_increment;
+
+ if (decrement) {
+ timer_increment = -timer_increment;
+ }
+
+ adjust_value (timer_increment);
+
+ have_timer = true;
+ timer_calls = 0;
+ timeout_tag = gtk_timeout_add (initial_timer_interval,
+ AutoSpin::_timer,
+ this);
+}
+
+gint
+AutoSpin::_timer (void *arg)
+{
+ return ((AutoSpin *) arg)->timer ();
+}
+
+void
+AutoSpin::set_value (gfloat value)
+{
+ adjustment.set_value (value);
+}
+
+bool
+AutoSpin::adjust_value (gfloat increment)
+{
+ gfloat val;
+ bool done = false;
+
+ val = adjustment.get_value();
+
+ val += increment;
+
+ if (val > upper) {
+ if (wrap) {
+ val = lower;
+ } else {
+ val = upper;
+ done = true;
+ }
+ } else if (val < lower) {
+ if (wrap) {
+ val = upper;
+ } else {
+ val = lower;
+ done = true;
+ }
+ }
+
+ adjustment.set_value (val);
+ return done;
+}
+
+gint
+AutoSpin::timer ()
+{
+ bool done;
+ int retval = FALSE;
+
+ done = adjust_value (timer_increment);
+
+ if (need_timer) {
+
+ /* we're in the initial call, which happened
+ after initial_timer_interval msecs. Now
+ request a much more frequent update.
+ */
+
+ timeout_tag = gtk_timeout_add (timer_interval,
+ _timer,
+ this);
+ have_timer = true;
+ need_timer = false;
+
+ /* cancel this initial timeout */
+
+ retval = FALSE;
+
+ } else {
+ /* this is the regular "fast" call after each
+ timer_interval msecs.
+ */
+
+ if (timer_calls < climb_timer_calls) {
+ timer_calls++;
+ } else {
+ if (climb_rate > 0.0) {
+ if (timer_increment > 0) {
+ timer_increment += climb_rate;
+ } else {
+ timer_increment -= climb_rate;
+ }
+ }
+ timer_calls = 0;
+ }
+
+ if (!done) {
+ retval = TRUE;
+ }
+ }
+
+ return retval;
+}
+
+void
+AutoSpin::set_bounds (gfloat init, gfloat up, gfloat down, bool with_reset)
+{
+ adjustment.set_upper(up);
+ adjustment.set_lower(down);
+
+ adjustment.changed ();
+
+ if (with_reset) {
+ adjustment.set_value (init);
+ }
+}
diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc
new file mode 100644
index 0000000000..01a952f558
--- /dev/null
+++ b/libs/gtkmm2ext/barcontroller.cc
@@ -0,0 +1,497 @@
+/*
+ Copyright (C) 2004 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+#include <climits>
+#include <cstdio>
+#include <cmath>
+#include <algorithm>
+
+#include <midi++/controllable.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/barcontroller.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+
+BarController::BarController (Gtk::Adjustment& adj,
+ MIDI::Controllable *mc,
+ sigc::slot<void,char*,unsigned int> lc)
+
+ : adjustment (adj),
+ prompter (Gtk::WIN_POS_MOUSE, 30000, false),
+ midi_control (mc),
+ label_callback (lc),
+ spinner (adjustment),
+ bind_button (2),
+ bind_statemask (Gdk::CONTROL_MASK)
+
+{
+ _style = LeftToRight;
+ grabbed = false;
+ switching = false;
+ switch_on_release = false;
+ with_text = true;
+ use_parent = false;
+
+ set_shadow_type (SHADOW_NONE);
+
+ initial_value = adjustment.get_value ();
+
+ adjustment.signal_value_changed().connect (mem_fun (*this, &Gtk::Widget::queue_draw));
+ adjustment.signal_changed().connect (mem_fun (*this, &Gtk::Widget::queue_draw));
+
+ darea.add_events (Gdk::BUTTON_RELEASE_MASK|
+ Gdk::BUTTON_PRESS_MASK|
+ Gdk::POINTER_MOTION_MASK|
+ Gdk::ENTER_NOTIFY_MASK|
+ Gdk::LEAVE_NOTIFY_MASK);
+
+ darea.signal_expose_event().connect (mem_fun (*this, &BarController::expose));
+ darea.signal_motion_notify_event().connect (mem_fun (*this, &BarController::motion));
+ darea.signal_button_press_event().connect (mem_fun (*this, &BarController::button_press));
+ darea.signal_button_release_event().connect (mem_fun (*this, &BarController::button_release));
+
+ prompter.signal_unmap_event().connect (mem_fun (*this, &BarController::prompter_hiding));
+
+ prompting = false;
+ unprompting = false;
+
+ if (mc) {
+ mc->learning_started.connect (mem_fun (*this, &BarController::midicontrol_prompt));
+ mc->learning_stopped.connect (mem_fun (*this, &BarController::midicontrol_unprompt));
+ }
+
+ spinner.signal_activate().connect (mem_fun (*this, &BarController::entry_activated));
+ spinner.signal_focus_out_event().connect (mem_fun (*this, &BarController::entry_focus_out));
+ spinner.set_digits (3);
+
+ add (darea);
+ show_all ();
+}
+
+void
+BarController::set_bind_button_state (guint button, guint statemask)
+{
+ bind_button = button;
+ bind_statemask = statemask;
+}
+
+void
+BarController::get_bind_button_state (guint &button, guint &statemask)
+{
+ button = bind_button;
+ statemask = bind_statemask;
+}
+
+
+gint
+BarController::button_press (GdkEventButton* ev)
+{
+ switch (ev->button) {
+ case 1:
+ if (ev->type == GDK_2BUTTON_PRESS) {
+ switch_on_release = true;
+ } else {
+ switch_on_release = false;
+ darea.add_modal_grab();
+ grabbed = true;
+ grab_x = ev->x;
+ grab_window = ev->window;
+ StartGesture ();
+ }
+ return TRUE;
+ break;
+
+ case 2:
+ case 3:
+ break;
+
+ case 4:
+ case 5:
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+BarController::button_release (GdkEventButton* ev)
+{
+ switch (ev->button) {
+ case 1:
+ if (switch_on_release) {
+ Glib::signal_idle().connect (mem_fun (*this, &BarController::switch_to_spinner));
+ return TRUE;
+ }
+
+ if ((ev->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == GDK_SHIFT_MASK) {
+ adjustment.set_value (initial_value);
+ } else {
+ double scale;
+
+ if (ev->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK) == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) {
+ scale = 0.01;
+ } else if (ev->state & GDK_CONTROL_MASK) {
+ scale = 0.1;
+ } else {
+ scale = 1.0;
+ }
+
+ mouse_control (ev->x, ev->window, scale);
+ }
+ grabbed = false;
+ darea.remove_modal_grab();
+ StopGesture ();
+ break;
+
+ case 2:
+ if ((ev->state & bind_statemask) && bind_button == 2) {
+ midi_learn ();
+ } else {
+ double fract;
+ fract = ev->x / (darea.get_width() - 2.0);
+ adjustment.set_value (adjustment.get_lower() +
+ fract * (adjustment.get_upper() - adjustment.get_lower()));
+ }
+ return TRUE;
+
+ case 3:
+ if ((ev->state & bind_statemask) && bind_button == 3) {
+ midi_learn ();
+ return TRUE;
+ }
+ return FALSE;
+
+ case 4:
+ adjustment.set_value (adjustment.get_value() +
+ adjustment.get_step_increment());
+ break;
+ case 5:
+ adjustment.set_value (adjustment.get_value() -
+ adjustment.get_step_increment());
+ break;
+ }
+
+ return TRUE;
+}
+
+gint
+BarController::motion (GdkEventMotion* ev)
+{
+ double scale;
+
+ if (!grabbed) {
+ return TRUE;
+ }
+
+ if ((ev->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == GDK_SHIFT_MASK) {
+ return TRUE;
+ }
+
+ if (ev->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK) == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) {
+ scale = 0.01;
+ } else if (ev->state & GDK_CONTROL_MASK) {
+ scale = 0.1;
+ } else {
+ scale = 1.0;
+ }
+
+ return mouse_control (ev->x, ev->window, scale);
+}
+
+gint
+BarController::mouse_control (double x, GdkWindow* window, double scaling)
+{
+ double fract;
+ double delta;
+
+ if (window != grab_window) {
+ grab_x = x;
+ grab_window = window;
+ return TRUE;
+ }
+
+ delta = x - grab_x;
+ grab_x = x;
+
+ switch (_style) {
+ case Line:
+ case LeftToRight:
+ fract = scaling * (delta / (darea.get_width() - 2));
+ fract = min (1.0, fract);
+ fract = max (-1.0, fract);
+ adjustment.set_value (adjustment.get_value() + fract * (adjustment.get_upper() - adjustment.get_lower()));
+ break;
+
+ default:
+ fract = 0.0;
+ }
+
+
+ return TRUE;
+}
+
+gint
+BarController::expose (GdkEventExpose* event)
+{
+ Glib::RefPtr<Gdk::Window> win (darea.get_window());
+ Widget* parent;
+ gint x1, x2, y1, y2;
+ gint w, h;
+ double fract;
+
+ w = darea.get_width() - 2;
+ h = darea.get_height() - 2;
+
+ fract = ((adjustment.get_value() - adjustment.get_lower()) /
+ (adjustment.get_upper() - adjustment.get_lower()));
+
+ switch (_style) {
+ case Line:
+ x1 = (gint) floor (w * fract);
+ x2 = x1;
+ y1 = 0;
+ y2 = h - 1;
+
+ if (use_parent) {
+ parent = get_parent();
+
+ if (parent) {
+ win->draw_rectangle (parent->get_style()->get_fg_gc (parent->get_state()),
+ true,
+ 0, 0, darea.get_width(), darea.get_height());
+ }
+ } else {
+ win->draw_rectangle (get_style()->get_bg_gc (get_state()),
+ true,
+ 0, 0, darea.get_width(), darea.get_height());
+ }
+
+ if (fract == 0.0) {
+ win->draw_rectangle (get_style()->get_fg_gc (get_state()),
+ true, x1, 1, 2, darea.get_height() - 2);
+ } else {
+ win->draw_rectangle (get_style()->get_fg_gc (get_state()),
+ true, x1 - 1, 1, 3, darea.get_height() - 2);
+ }
+ break;
+
+ case CenterOut:
+ break;
+
+ case LeftToRight:
+ x1 = 0;
+ x2 = (gint) floor (w * fract);
+ y1 = 0;
+ y2 = h - 1;
+
+ win->draw_rectangle (get_style()->get_bg_gc (get_state()),
+ false,
+ 0, 0, darea.get_width(), darea.get_height());
+
+ /* draw active box */
+
+ win->draw_rectangle (get_style()->get_fg_gc (get_state()),
+ true,
+ 1 + x1,
+ 1 + y1,
+ x2,
+ 1 + y2);
+
+ /* draw inactive box */
+
+ win->draw_rectangle (get_style()->get_fg_gc (STATE_INSENSITIVE),
+ true,
+ 1 + x2,
+ 1 + y1,
+ w - x2,
+ 1 + y2);
+
+ break;
+
+ case RightToLeft:
+ break;
+ case TopToBottom:
+ break;
+ case BottomToTop:
+ break;
+ }
+
+ if (with_text) {
+ /* draw label */
+
+ char buf[64];
+ buf[0] = '\0';
+
+ label_callback (buf, 64);
+
+ if (buf[0] != '\0') {
+ int width = 0, height;
+ darea.create_pango_layout(buf)->get_pixel_size(width, height);
+ darea.set_size_request(width + 2, -1);
+ }
+ }
+ return TRUE;
+}
+
+void
+BarController::set_with_text (bool yn)
+{
+ if (with_text != yn) {
+ with_text = yn;
+ queue_draw ();
+ }
+}
+
+void
+BarController::midicontrol_set_tip ()
+{
+ if (midi_control) {
+ // Gtkmm2ext::UI::instance()->set_tip (&darea, midi_control->control_description());
+ }
+}
+
+void
+BarController::midi_learn()
+{
+ if (midi_control) {
+ prompting = true;
+ midi_control->learn_about_external_control ();
+ }
+}
+
+
+void
+BarController::midicontrol_prompt ()
+{
+ if (prompting) {
+ string prompt = _("operate MIDI controller now");
+ prompter.set_text (prompt);
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+
+ unprompting = true;
+ prompting = false;
+ }
+}
+
+void
+BarController::midicontrol_unprompt ()
+{
+ if (unprompting) {
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+
+ unprompting = false;
+ }
+}
+
+gint
+BarController::prompter_hiding (GdkEventAny *ev)
+{
+ if (unprompting) {
+ if (midi_control) {
+ midi_control->stop_learning();
+ }
+ unprompting = false;
+ }
+
+ return FALSE;
+}
+
+
+void
+BarController::set_style (Style s)
+{
+ _style = s;
+ darea.queue_draw ();
+}
+
+gint
+BarController::switch_to_bar ()
+{
+ if (switching) {
+ return FALSE;
+ }
+
+ switching = true;
+
+ if (get_child() == &darea) {
+ return FALSE;
+ }
+
+ remove ();
+ add (darea);
+ darea.show ();
+
+ switching = false;
+ return FALSE;
+}
+
+gint
+BarController::switch_to_spinner ()
+{
+ if (switching) {
+ return FALSE;
+ }
+
+ switching = true;
+
+ if (get_child() == &spinner) {
+ return FALSE;
+ }
+
+ remove ();
+ add (spinner);
+ spinner.show ();
+ spinner.grab_focus ();
+
+ switching = false;
+ return FALSE;
+}
+
+void
+BarController::entry_activated ()
+{
+ string text = spinner.get_text ();
+ float val;
+
+ if (sscanf (text.c_str(), "%f", &val) == 1) {
+ adjustment.set_value (val);
+ }
+
+ switch_to_bar ();
+}
+
+gint
+BarController::entry_focus_out (GdkEventFocus* ev)
+{
+ entry_activated ();
+ return TRUE;
+}
+
+void
+BarController::set_use_parent (bool yn)
+{
+ use_parent = yn;
+ queue_draw ();
+}
diff --git a/libs/gtkmm2ext/bindable_button.cc b/libs/gtkmm2ext/bindable_button.cc
new file mode 100644
index 0000000000..c2516a9219
--- /dev/null
+++ b/libs/gtkmm2ext/bindable_button.cc
@@ -0,0 +1,155 @@
+/*
+ Copyright (C) 2004 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+#include <climits>
+#include <iostream>
+
+#include <midi++/controllable.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/bindable_button.h>
+
+#include "i18n.h"
+
+using namespace Gtkmm2ext;
+using namespace std;
+
+BindableToggleButton::BindableToggleButton (MIDI::Controllable *mc)
+ : ToggleButton (),
+ prompter (Gtk::WIN_POS_MOUSE, 30000, false),
+ midi_control (mc),
+ bind_button (2),
+ bind_statemask (Gdk::CONTROL_MASK)
+
+{
+ init_events ();
+}
+
+BindableToggleButton::BindableToggleButton(MIDI::Controllable *mc, const string &label)
+ : ToggleButton (label),
+ prompter (Gtk::WIN_POS_MOUSE, 30000, false),
+ midi_control (mc),
+ bind_button (2),
+ bind_statemask (Gdk::CONTROL_MASK)
+{
+ init_events ();
+}
+
+
+void
+BindableToggleButton::init_events ()
+{
+ signal_button_press_event().connect (mem_fun (*this, &BindableToggleButton::button_press));
+
+ prompter.signal_unmap_event().connect (mem_fun (*this, &BindableToggleButton::prompter_hiding));
+
+ prompting = false;
+ unprompting = false;
+
+ if (midi_control) {
+ midi_control->learning_started.connect (mem_fun (*this, &BindableToggleButton::midicontrol_prompt));
+ midi_control->learning_stopped.connect (mem_fun (*this, &BindableToggleButton::midicontrol_unprompt));
+ }
+}
+
+void
+BindableToggleButton::set_bind_button_state (guint button, guint statemask)
+{
+ bind_button = button;
+ bind_statemask = statemask;
+}
+
+void
+BindableToggleButton::get_bind_button_state (guint &button, guint &statemask)
+{
+ button = bind_button;
+ statemask = bind_statemask;
+}
+
+void
+BindableToggleButton::midi_learn()
+{
+ if (midi_control) {
+ prompting = true;
+ midi_control->learn_about_external_control ();
+ }
+}
+
+
+gint
+BindableToggleButton::button_press (GdkEventButton *ev)
+{
+
+ if ((ev->state & bind_statemask) && ev->button == bind_button) {
+ midi_learn ();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+BindableToggleButton::prompter_hiding (GdkEventAny *ev)
+{
+ if (unprompting) {
+ if (midi_control) {
+ midi_control->stop_learning();
+ }
+ unprompting = false;
+ }
+
+ return FALSE;
+}
+
+
+void
+BindableToggleButton::midicontrol_set_tip ()
+
+{
+ if (midi_control) {
+ // Gtkmm2ext::UI::instance()->set_tip (evbox, midi_control->control_description());
+ }
+}
+
+void
+BindableToggleButton::midicontrol_prompt ()
+
+{
+ if (prompting) {
+ string prompt = _("operate MIDI controller now");
+ prompter.set_text (prompt);
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+
+ unprompting = true;
+ prompting = false;
+ }
+}
+
+void
+BindableToggleButton::midicontrol_unprompt ()
+
+{
+ if (unprompting) {
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+ unprompting = false;
+ }
+}
+
+
diff --git a/libs/gtkmm2ext/choice.cc b/libs/gtkmm2ext/choice.cc
new file mode 100644
index 0000000000..5a3b7d0140
--- /dev/null
+++ b/libs/gtkmm2ext/choice.cc
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtkmm2ext/choice.h>
+
+using namespace std;
+using namespace Gtkmm2ext;
+using namespace sigc;
+using namespace Gtk;
+
+Choice::Choice (string prompt,
+ vector<string> choices)
+ : Gtk::Window (WINDOW_TOPLEVEL),
+ prompt_label (prompt)
+{
+ int n;
+ vector<string>::iterator i;
+
+ set_position (WIN_POS_MOUSE);
+ set_name ("ChoiceWindow");
+ add (packer);
+
+ packer.set_spacing (10);
+ packer.set_border_width (10);
+ packer.pack_start (prompt_label);
+ packer.pack_start (button_packer);
+ prompt_label.set_name ("ChoicePrompt");
+
+ for (n = 0, i = choices.begin(); i != choices.end(); ++i, ++n) {
+ Button *button = manage (new Gtk::Button (*i));
+ button->set_name ("ChoiceButton");
+
+ button_packer.set_spacing (5);
+ button_packer.set_homogeneous (true);
+ button_packer.pack_start (*button, false, true);
+
+ button->signal_clicked().connect (bind (mem_fun (*this, &Choice::_choice_made), n));
+ buttons.push_back (button);
+ }
+
+ signal_delete_event().connect(mem_fun(*this, &Choice::closed));
+
+ packer.show_all ();
+ which_choice = -1;
+}
+
+void
+Choice::on_realize ()
+{
+ Gtk::Window::on_realize();
+ Glib::RefPtr<Gdk::Window> win (get_window());
+ win->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
+}
+
+Choice::~Choice ()
+{
+}
+
+void
+Choice::_choice_made (int nbutton)
+{
+ which_choice = nbutton;
+ choice_made (which_choice);
+ chosen ();
+}
+
+gint
+Choice::closed (GdkEventAny *ev)
+{
+ which_choice = -1;
+ choice_made (which_choice);
+ chosen ();
+ return TRUE;
+}
+
+int
+Choice::get_choice ()
+{
+ return which_choice;
+}
diff --git a/libs/gtkmm2ext/click_box.cc b/libs/gtkmm2ext/click_box.cc
new file mode 100644
index 0000000000..6bd03282eb
--- /dev/null
+++ b/libs/gtkmm2ext/click_box.cc
@@ -0,0 +1,125 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+#include <cstdio> /* for sprintf, sigh ... */
+
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/click_box.h>
+
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace sigc;
+
+ClickBox::ClickBox (Gtk::Adjustment *adjp, const string &name)
+ : AutoSpin (*adjp)
+{
+ print_func = default_printer;
+ print_arg = 0;
+
+ set_name (name);
+ add_events (Gdk::BUTTON_RELEASE_MASK|
+ Gdk::BUTTON_PRESS_MASK|
+ Gdk::ENTER_NOTIFY_MASK|
+ Gdk::LEAVE_NOTIFY_MASK);
+ set_label ();
+
+ get_adjustment().signal_value_changed().connect (mem_fun (*this, &ClickBox::set_label));
+
+ signal_button_press_event().connect (mem_fun (*this, &ClickBox::button_press_handler));
+ signal_button_release_event().connect (mem_fun (*this, &ClickBox::button_release_handler));
+}
+
+ClickBox::~ClickBox ()
+{
+}
+
+bool
+ClickBox::button_press_handler (GdkEventButton* ev)
+{
+ add_modal_grab();
+ AutoSpin::button_press (ev);
+ return true;
+}
+
+bool
+ClickBox::button_release_handler (GdkEventButton* ev)
+{
+ switch (ev->button) {
+ case 1:
+ case 2:
+ case 3:
+ stop_spinning (0);
+ remove_modal_grab();
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+void
+ClickBox::default_printer (char buf[32], Gtk::Adjustment &adj,
+ void *ignored)
+{
+ sprintf (buf, "%.2f", adj.get_value());
+}
+
+void
+ClickBox::set_label ()
+{
+ queue_draw ();
+}
+
+bool
+ClickBox::on_expose_event (GdkEventExpose *ev)
+{
+ /* Why do we do things like this rather than use a Gtk::Label?
+ Because whenever Gtk::Label::set_label() is called, it
+ triggers a recomputation of its own size, along with that
+ of its container and on up the tree. That's intended
+ to be unnecessary here.
+ */
+
+ Gtk::DrawingArea::on_expose_event (ev);
+
+ if (print_func) {
+
+ char buf[32];
+
+ Glib::RefPtr<Gtk::Style> style (get_style());
+
+ print_func (buf, get_adjustment(), print_arg);
+
+ Glib::RefPtr <Gdk::Window> win (get_window());
+ win->draw_rectangle (style->get_bg_gc(get_state()),
+ TRUE, 0, 0, -1, -1);
+
+ {
+ int width = 0;
+ int height = 0;
+ create_pango_layout(buf)->get_pixel_size(width, height);
+ set_size_request(width, height);
+ }
+ }
+
+ return true;
+}
diff --git a/libs/gtkmm2ext/controller.cc b/libs/gtkmm2ext/controller.cc
new file mode 100644
index 0000000000..98d5566c69
--- /dev/null
+++ b/libs/gtkmm2ext/controller.cc
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 1998-99 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+#include <climits>
+
+#include <midi++/channel.h>
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/controller.h>
+
+#include "i18n.h"
+
+using namespace Gtkmm2ext;
+
+Controller::Controller (Gtk::Adjustment *adj, MIDI::Port *p)
+ : MIDI::Controllable (p),
+ adjustment (adj),
+ prompter (Gtk::WIN_POS_MOUSE, 30000, false)
+{
+ new_value_pending = false;
+
+ /* hear about MIDI control learning */
+
+ learning_started.connect
+ (mem_fun (*this, &Controller::midicontrol_prompt));
+ learning_stopped.connect
+ (mem_fun (*this, &Controller::midicontrol_unprompt));
+}
+
+void
+Controller::midicontrol_prompt ()
+
+{
+ string prompt = _("operate MIDI controller now");
+
+ prompter.set_text (prompt);
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+}
+
+void
+Controller::midicontrol_unprompt ()
+
+{
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+}
+
+int
+Controller::update_controller_value (void *arg)
+
+{
+ Controller *c = (Controller *) arg;
+
+ c->adjustment->set_value (c->new_value);
+ c->new_value_pending = false;
+
+ return FALSE;
+}
+
+void
+Controller::set_value (float v)
+
+{
+ /* This is called from a MIDI callback. It could happen
+ a thousand times a second, or more. Therefore, instead
+ of going straight to the X server, which may not work for
+ thread-related reasons, simply request an update whenever
+ the GTK main loop is idle.
+ */
+
+ new_value = v;
+
+ if (!new_value_pending) {
+ new_value_pending = true;
+ Gtkmm2ext::UI::instance()->idle_add (update_controller_value, this);
+ }
+}
diff --git a/libs/gtkmm2ext/fastmeter.cc b/libs/gtkmm2ext/fastmeter.cc
new file mode 100644
index 0000000000..3eff07e915
--- /dev/null
+++ b/libs/gtkmm2ext/fastmeter.cc
@@ -0,0 +1,291 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+#include <cmath>
+#include <algorithm>
+#include <gdkmm/rectangle.h>
+#include <gtkmm2ext/fastmeter.h>
+#include <gtkmm/style.h>
+
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace std;
+
+Glib::RefPtr<Gdk::Pixmap> *FastMeter::v_pixmap = 0;
+Glib::RefPtr<Gdk::Bitmap> *FastMeter::v_mask = 0;
+gint FastMeter::v_pixheight = 0;
+gint FastMeter::v_pixwidth = 0;
+
+Glib::RefPtr<Gdk::Pixmap> *FastMeter::h_pixmap = 0;
+Glib::RefPtr<Gdk::Bitmap> *FastMeter::h_mask = 0;
+gint FastMeter::h_pixheight = 0;
+gint FastMeter::h_pixwidth = 0;
+
+FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o)
+{
+ orientation = o;
+ hold_cnt = hold;
+ hold_state = 0;
+ current_peak = 0;
+ current_level = 0;
+ current_user_level = -100.0f;
+
+ set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+
+ pixrect.set_x(0);
+ pixrect.set_y(0);
+
+ if (orientation == Vertical) {
+ pixrect.set_width(min (v_pixwidth, (gint) dimen));
+ pixrect.set_height(v_pixheight);
+ } else {
+ pixrect.set_width(h_pixwidth);
+ pixrect.set_height(min (h_pixheight, (gint) dimen));
+ }
+
+ request_width = pixrect.get_width();
+ request_height= pixrect.get_height();
+
+ backing = 0;
+}
+
+FastMeter::~FastMeter ()
+{
+ if (backing) {
+ (*backing)->unreference();
+ }
+}
+
+void
+FastMeter::set_vertical_xpm (const char **xpm)
+{
+ if (v_pixmap == 0) {
+ gint w, h;
+
+ *v_pixmap = Gdk::Pixmap::create_from_xpm(Gdk::Colormap::get_system(), *v_mask, xpm);
+
+ (*v_pixmap)->get_size(w, h);
+
+ v_pixheight = h;
+ v_pixwidth = w;
+ }
+}
+
+void
+FastMeter::set_horizontal_xpm (const char **xpm)
+{
+ if (h_pixmap == 0) {
+ gint w, h;
+
+ *h_pixmap = Gdk::Pixmap::create_from_xpm(Gdk::Colormap::get_system(), *h_mask, xpm);
+
+ (*h_pixmap)->get_size(w, h);
+
+ h_pixheight = h;
+ h_pixwidth = w;
+ }
+}
+
+void
+FastMeter::set_hold_count (long val)
+{
+ if (val < 1) {
+ val = 1;
+ }
+
+ hold_cnt = val;
+ hold_state = 0;
+ current_peak = 0;
+
+ queue_draw ();
+}
+
+void
+FastMeter::on_size_request (GtkRequisition* req)
+{
+ req->width = request_width;
+ req->height = request_height;
+}
+
+bool
+FastMeter::on_expose_event (GdkEventExpose* ev)
+{
+ if (orientation == Vertical) {
+ return vertical_expose (ev);
+ } else {
+ return horizontal_expose (ev);
+ }
+}
+
+bool
+FastMeter::vertical_expose (GdkEventExpose* ev)
+{
+ Gdk::Rectangle intersect;
+ gint top_of_meter;
+ bool blit = false;
+ bool intersecting = false;
+
+ top_of_meter = (gint) floor (v_pixheight * current_level);
+ pixrect.set_height(v_pixheight - top_of_meter); /* bottom of background */
+
+ if (backing == 0) {
+ *backing = Gdk::Pixmap::create (get_window(), get_width(), get_height());
+ }
+
+ intersect = pixrect.intersect(Glib::wrap(&ev->area), intersecting);
+ if (intersecting) {
+
+ /* paint the background (black). */
+ (*backing)->draw_rectangle(get_style()->get_black_gc(), true, intersect.get_x(), intersect.get_y(), intersect.get_width(), intersect.get_height());
+ blit = true;
+ }
+
+ pixrect.set_height(top_of_meter);
+
+ intersect = pixrect.intersect(Glib::wrap(&ev->area), intersecting);
+ if (intersecting) {
+ /* draw the part of the meter image that we need. the area we draw is bounded "in reverse" (top->bottom)
+ */
+
+ (*backing)->draw_drawable(get_style()->get_fg_gc(get_state()), *v_pixmap,
+ intersect.get_x(), v_pixheight - top_of_meter,
+ intersect.get_x(), v_pixheight - top_of_meter,
+ intersect.get_width(), intersect.get_height());
+
+ blit = true;
+ }
+
+ /* draw peak bar */
+
+ if (hold_state) {
+ (*backing)->draw_drawable(get_style()->get_fg_gc(get_state()), *v_pixmap,
+ intersect.get_x(), v_pixheight - (gint) floor (v_pixheight * current_peak),
+ intersect.get_x(), v_pixheight - (gint) floor (v_pixheight * current_peak),
+ intersect.get_width(), 3);
+ }
+
+ /* bilt to on-screen drawable */
+
+ if (blit) {
+ Glib::RefPtr<Gdk::Window> win (get_window());
+ win->draw_drawable(get_style()->get_fg_gc(get_state()), *backing,
+ ev->area.x, ev->area.y,
+ ev->area.x, ev->area.y,
+ ev->area.width, ev->area.height);
+ }
+
+ return true;
+}
+
+bool
+FastMeter::horizontal_expose (GdkEventExpose* ev)
+{
+ Gdk::Rectangle intersect;
+ bool intersecting = false;
+ gint right_of_meter;
+ bool blit = false;
+
+ right_of_meter = (gint) floor (h_pixwidth * current_level);
+
+ pixrect.set_x(right_of_meter);
+ pixrect.set_y(0);
+ pixrect.set_width(h_pixwidth - right_of_meter);
+
+ if (backing == 0) {
+ *backing = Gdk::Pixmap::create(get_window(), get_width(), get_height());
+ }
+
+ intersect = pixrect.intersect(Glib::wrap(&ev->area), intersecting);
+ if (intersecting) {
+ /* paint the background (black). */
+
+ (*backing)->draw_rectangle(get_style()->get_black_gc(), true,
+ intersect.get_x(), intersect.get_y(),
+ intersect.get_width(), intersect.get_height());
+ blit = true;
+ }
+
+ pixrect.set_x(0);
+ pixrect.set_width(right_of_meter);
+
+ intersect = pixrect.intersect(Glib::wrap(&ev->area), intersecting);
+ if (intersecting) {
+ /* draw the part of the meter image that we need.
+ */
+
+ (*backing)->draw_drawable(get_style()->get_fg_gc(get_state()), *h_pixmap,
+ intersect.get_x(), intersect.get_y(),
+ intersect.get_x(), intersect.get_y(),
+ intersect.get_width(), intersect.get_height());
+
+ blit = true;
+ }
+
+ /* draw peak bar */
+
+ if (hold_state) {
+ (*backing)->draw_drawable(get_style()->get_fg_gc(get_state()), *h_pixmap,
+ right_of_meter, intersect.get_y(),
+ right_of_meter, intersect.get_y(),
+ 3, intersect.get_height());
+ }
+
+ /* bilt to on-screen drawable */
+
+ if (blit) {
+ Glib::RefPtr<Gdk::Window> win(get_window());
+ win->draw_drawable(get_style()->get_fg_gc(get_state()), *backing,
+ ev->area.x, ev->area.y,
+ ev->area.x, ev->area.y,
+ ev->area.width, ev->area.height);
+ }
+
+ return true;
+}
+
+void
+FastMeter::set (float lvl, float usrlvl)
+{
+ current_level = lvl;
+ current_user_level = usrlvl;
+
+ if (lvl > current_peak) {
+ current_peak = lvl;
+ hold_state = hold_cnt;
+ }
+
+ if (hold_state > 0) {
+ if (--hold_state == 0) {
+ current_peak = lvl;
+ }
+ }
+
+ queue_draw ();
+}
+
+void
+FastMeter::clear ()
+{
+ current_level = 0;
+ current_peak = 0;
+ hold_state = 0;
+ queue_draw ();
+}
diff --git a/libs/gtkmm2ext/gettext.h b/libs/gtkmm2ext/gettext.h
new file mode 100644
index 0000000000..339c74ffe7
--- /dev/null
+++ b/libs/gtkmm2ext/gettext.h
@@ -0,0 +1,82 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+ Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option. */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions. */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+ chokes if dcgettext is defined as a macro. So include it now, to make
+ later inclusions of <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+ The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions.
+ On pre-ANSI systems without 'const', the config.h file is supposed to
+ contain "#define const". */
+
+/* other headers may have included libintl.h */
+
+# undef gettext
+# undef dgettext
+# undef dcgettext
+# undef ngettext
+# undef dngettext
+# undef dcngettext
+# undef textdomain
+# undef bindtextdomain
+# undef bind_textdomain_codeset
+
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+ extraction of messages, but does not call gettext(). The run-time
+ translation is done at a different place in the code.
+ The argument, String, should be a literal string. Concatenated strings
+ and other string expressions won't work.
+ The macro's expansion is not parenthesized, so that it is suitable as
+ initializer for static 'char[]' or 'const char[]' variables. */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc
new file mode 100644
index 0000000000..d2a551144d
--- /dev/null
+++ b/libs/gtkmm2ext/gtk_ui.cc
@@ -0,0 +1,823 @@
+/*
+ Copyright (C) 1999-2002 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <cerrno>
+#include <climits>
+#include <cctype>
+
+#include <gtkmm.h>
+#include <pbd/error.h>
+#include <pbd/touchable.h>
+#include <pbd/failed_constructor.h>
+#include <pbd/pthread_utils.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/textviewer.h>
+#include <gtkmm2ext/popup.h>
+#include <gtkmm2ext/utils.h>
+
+#include "i18n.h"
+
+using namespace Gtkmm2ext;
+using std::map;
+
+pthread_t UI::gui_thread;
+UI *UI::theGtkUI = 0;
+
+UI::UI (string name, int *argc, char ***argv, string rcfile)
+ : _ui_name (name)
+{
+ theMain = new Gtk::Main (argc, argv);
+ tips = new Gtk::Tooltips;
+
+ if (pthread_key_create (&thread_request_buffer_key, 0)) {
+ cerr << _("cannot create thread request buffer key") << endl;
+ throw failed_constructor();
+ }
+
+ PBD::ThreadCreated.connect (mem_fun (*this, &UI::register_thread));
+
+ _ok = false;
+ _active = false;
+
+ if (!theGtkUI) {
+ theGtkUI = this;
+ gui_thread = pthread_self ();
+ } else {
+ fatal << "duplicate UI requested" << endmsg;
+ /* NOTREACHED */
+ }
+
+ if (setup_signal_pipe ()) {
+ return;
+ }
+
+ load_rcfile (rcfile);
+
+ errors = new TextViewer (850,100);
+ errors->text().set_editable (false);
+ errors->text().set_name ("ErrorText");
+
+ string title;
+ title = _ui_name;
+ title += ": Log";
+ errors->set_title (title);
+
+ errors->dismiss_button().set_name ("ErrorLogCloseButton");
+// errors->realize();
+
+ Glib::RefPtr<Gdk::Window> win(errors->get_window());
+ win->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
+
+ errors->signal_delete_event().connect (bind (ptr_fun (just_hide_it), (Gtk::Window *) errors));
+
+ register_thread (pthread_self(), X_("GUI"));
+
+ _ok = true;
+}
+
+UI::~UI ()
+{
+ close (signal_pipe[0]);
+ close (signal_pipe[1]);
+}
+
+int
+UI::load_rcfile (string path)
+{
+ if (path.length() == 0) {
+ return -1;
+ }
+
+ if (access (path.c_str(), R_OK)) {
+ error << "UI: couldn't find rc file \""
+ << path
+ << '"'
+ << endmsg;
+ return -1;
+ }
+
+ gtk_rc_parse (path.c_str());
+
+ Gtk::Label *a_widget1;
+ Gtk::Label *a_widget2;
+ Gtk::Label *a_widget3;
+ Gtk::Label *a_widget4;
+
+ a_widget1 = new Gtk::Label;
+ a_widget2 = new Gtk::Label;
+ a_widget3 = new Gtk::Label;
+ a_widget4 = new Gtk::Label;
+
+ a_widget1->set_name ("FatalMessage");
+ a_widget1->ensure_style ();
+ fatal_message_style = a_widget1->get_style();
+
+ a_widget2->set_name ("ErrorMessage");
+ a_widget2->ensure_style ();
+ error_message_style = a_widget2->get_style();
+
+ a_widget3->set_name ("WarningMessage");
+ a_widget3->ensure_style ();
+ warning_message_style = a_widget3->get_style();
+
+ a_widget4->set_name ("InfoMessage");
+ a_widget4->ensure_style ();
+ info_message_style = a_widget4->get_style();
+
+ delete a_widget1;
+ delete a_widget2;
+ delete a_widget3;
+ delete a_widget4;
+
+ return 0;
+}
+
+void
+UI::run (Receiver &old_receiver)
+{
+ listen_to (error);
+ listen_to (info);
+ listen_to (warning);
+ listen_to (fatal);
+
+ old_receiver.hangup ();
+ starting ();
+ _active = true;
+ theMain->run ();
+ _active = false;
+ stopping ();
+ hangup ();
+ return;
+}
+
+bool
+UI::running ()
+{
+ return _active;
+}
+
+void
+UI::kill ()
+{
+ if (_active) {
+ pthread_kill (gui_thread, SIGKILL);
+ }
+}
+
+void
+UI::quit ()
+{
+ request (Quit);
+}
+
+void
+UI::do_quit ()
+{
+ Gtk::Main::quit();
+}
+
+void
+UI::touch_display (Touchable *display)
+{
+ Request *req = get_request (TouchDisplay);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->display = display;
+
+ send_request (req);
+}
+
+void
+UI::call_slot (sigc::slot<void> slot)
+{
+ Request *req = get_request (CallSlot);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->slot = slot;
+
+ send_request (req);
+}
+
+void
+UI::call_slot_locked (sigc::slot<void> slot)
+{
+ if (caller_is_gui_thread()) {
+ call_slot (slot);
+ return;
+ }
+
+ Request *req = get_request (CallSlotLocked);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->slot = slot;
+
+ pthread_mutex_init (&req->slot_lock, NULL);
+ pthread_cond_init (&req->slot_cond, NULL);
+ pthread_mutex_lock (&req->slot_lock);
+
+ send_request (req);
+
+ pthread_cond_wait (&req->slot_cond, &req->slot_lock);
+ pthread_mutex_unlock (&req->slot_lock);
+
+ delete req;
+}
+
+void
+UI::set_tip (Gtk::Widget *w, const gchar *tip, const gchar *hlp)
+{
+ Request *req = get_request (SetTip);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->widget = w;
+ req->msg = tip;
+ req->msg2 = hlp;
+
+ send_request (req);
+}
+
+void
+UI::set_state (Gtk::Widget *w, Gtk::StateType state)
+{
+ Request *req = get_request (StateChange);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->new_state = state;
+ req->widget = w;
+
+ send_request (req);
+}
+
+void
+UI::idle_add (int (*func)(void *), void *arg)
+{
+ Request *req = get_request (AddIdle);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->function = func;
+ req->arg = arg;
+
+ send_request (req);
+}
+
+void
+UI::timeout_add (unsigned int timeout, int (*func)(void *), void *arg)
+{
+ Request *req = get_request (AddTimeout);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->function = func;
+ req->arg = arg;
+ req->timeout = timeout;
+
+ send_request (req);
+}
+
+/* END abstract_ui interfaces */
+
+/* Handling requests */
+
+void
+UI::register_thread (pthread_t thread_id, string name)
+{
+ RingBufferNPT<Request>* b = new RingBufferNPT<Request> (128);
+
+ {
+ PBD::LockMonitor lm (request_buffer_map_lock, __LINE__, __FILE__);
+ request_buffers[thread_id] = b;
+ }
+
+ pthread_setspecific (thread_request_buffer_key, b);
+}
+
+UI::Request::Request()
+{
+
+}
+
+UI::Request*
+UI::get_request (RequestType rt)
+{
+ RingBufferNPT<Request>* rbuf = static_cast<RingBufferNPT<Request>* >(pthread_getspecific (thread_request_buffer_key));
+
+ if (rbuf == 0) {
+ /* Cannot happen, but if it does we can't use the error reporting mechanism */
+ cerr << _("programming error: ")
+ << compose (X_("no GUI request buffer found for thread %1"), pthread_self())
+ << endl;
+ abort ();
+ }
+
+ RingBufferNPT<Request>::rw_vector vec;
+
+ rbuf->get_write_vector (&vec);
+
+ if (vec.len[0] == 0) {
+ if (vec.len[1] == 0) {
+ cerr << compose (X_("no space in GUI request buffer for thread %1"), pthread_self())
+ << endl;
+ return 0;
+ } else {
+ vec.buf[1]->type = rt;
+ return vec.buf[1];
+ }
+ } else {
+ vec.buf[0]->type = rt;
+ return vec.buf[0];
+ }
+}
+
+int
+UI::setup_signal_pipe ()
+{
+ /* setup the pipe that other threads send us notifications/requests
+ through.
+ */
+
+ if (pipe (signal_pipe)) {
+ error << "UI: cannot create error signal pipe ("
+ << strerror (errno) << ")"
+ << endmsg;
+
+ return -1;
+ }
+
+ if (fcntl (signal_pipe[0], F_SETFL, O_NONBLOCK)) {
+ error << "UI: cannot set O_NONBLOCK on "
+ "signal read pipe ("
+ << strerror (errno) << ")"
+ << endmsg;
+ return -1;
+ }
+
+ if (fcntl (signal_pipe[1], F_SETFL, O_NONBLOCK)) {
+ error << "UI: cannot set O_NONBLOCK on "
+ "signal write pipe ("
+ << strerror (errno)
+ << ")"
+ << endmsg;
+ return -1;
+ }
+
+ /* add the pipe to the select/poll loop that GDK does */
+
+ gdk_input_add (signal_pipe[0],
+ GDK_INPUT_READ,
+ UI::signal_pipe_callback,
+ this);
+
+ return 0;
+}
+
+void
+UI::signal_pipe_callback (void *arg, int fd, GdkInputCondition cond)
+{
+ char buf[256];
+
+ /* flush (nonblocking) pipe */
+
+ while (read (fd, buf, 256) > 0);
+
+ ((UI *) arg)->handle_ui_requests ();
+}
+
+void
+UI::handle_ui_requests ()
+{
+ RequestBufferMap::iterator i;
+
+ request_buffer_map_lock.lock ();
+
+ for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
+
+ RingBufferNPT<Request>::rw_vector vec;
+
+ while (true) {
+
+ /* we must process requests 1 by 1 because
+ the request may run a recursive main
+ event loop that will itself call
+ handle_ui_requests. when we return
+ from the request handler, we cannot
+ expect that the state of queued requests
+ is even remotely consistent with
+ the condition before we called it.
+ */
+
+ i->second->get_read_vector (&vec);
+
+ if (vec.len[0] == 0) {
+ break;
+ } else {
+ /* copy constructor does a deep
+ copy of the Request object,
+ unlike Ringbuffer::read()
+ */
+ Request req (*vec.buf[0]);
+ i->second->increment_read_ptr (1);
+ request_buffer_map_lock.unlock ();
+ do_request (&req);
+ request_buffer_map_lock.lock ();
+ }
+ }
+ }
+
+ request_buffer_map_lock.unlock ();
+}
+
+void
+UI::do_request (Request* req)
+{
+ switch (req->type) {
+ case ErrorMessage:
+ process_error_message (req->chn, req->msg);
+ free (const_cast<char*>(req->msg)); /* it was strdup'ed */
+ break;
+
+ case Quit:
+ do_quit ();
+ break;
+
+ case CallSlot:
+ req->slot ();
+ break;
+
+ case CallSlotLocked:
+ pthread_mutex_lock (&req->slot_lock);
+ req->slot ();
+ pthread_cond_signal (&req->slot_cond);
+ pthread_mutex_unlock (&req->slot_lock);
+ break;
+
+ case TouchDisplay:
+ req->display->touch ();
+ if (req->display->delete_after_touch()) {
+ delete req->display;
+ }
+ break;
+
+ case StateChange:
+ req->widget->set_state (req->new_state);
+ break;
+
+ case SetTip:
+ /* XXX need to figure out how this works */
+ break;
+
+ case AddIdle:
+ gtk_idle_add (req->function, req->arg);
+ break;
+
+ case AddTimeout:
+ gtk_timeout_add (req->timeout, req->function, req->arg);
+ break;
+
+ default:
+ error << "UI: unknown request type "
+ << (int) req->type
+ << endmsg;
+ }
+}
+
+void
+UI::send_request (Request *req)
+{
+ if (instance() == 0) {
+ return; /* XXX is this the right thing to do ? */
+ }
+
+ if (caller_is_gui_thread()) {
+ // cerr << "GUI thread sent request " << req << " type = " << req->type << endl;
+ do_request (req);
+ } else {
+ const char c = 0;
+ RingBufferNPT<Request*>* rbuf = static_cast<RingBufferNPT<Request*> *> (pthread_getspecific (thread_request_buffer_key));
+
+ if (rbuf == 0) {
+ /* can't use the error system to report this, because this
+ thread isn't registered!
+ */
+ cerr << _("programming error: ")
+ << compose (X_("UI::send_request() called from %1, but no request buffer exists for that thread"),
+ pthread_self())
+ << endl;
+ abort ();
+ }
+
+ // cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
+ rbuf->increment_write_ptr (1);
+ write (signal_pipe[1], &c, 1);
+ }
+}
+
+void
+UI::request (RequestType rt)
+{
+ Request *req = get_request (rt);
+
+ if (req == 0) {
+ return;
+ }
+
+ send_request (req);
+}
+
+/*======================================================================
+ Error Display
+ ======================================================================*/
+
+void
+UI::receive (Transmitter::Channel chn, const char *str)
+{
+ if (caller_is_gui_thread()) {
+ process_error_message (chn, str);
+ } else {
+ Request* req = get_request (ErrorMessage);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->chn = chn;
+ req->msg = strdup (str);
+
+ send_request (req);
+ }
+}
+
+#define OLD_STYLE_ERRORS 1
+
+void
+UI::process_error_message (Transmitter::Channel chn, const char *str)
+{
+ Glib::RefPtr<Gtk::Style> style;
+ char *prefix;
+ size_t prefix_len;
+ bool fatal_received = false;
+#ifndef OLD_STYLE_ERRORS
+ PopUp* popup = new PopUp (Gtk::WIN_POS_CENTER, 0, true);
+#endif
+
+ switch (chn) {
+ case Transmitter::Fatal:
+ prefix = "[FATAL]: ";
+ style = fatal_message_style;
+ prefix_len = 9;
+ fatal_received = true;
+ break;
+ case Transmitter::Error:
+#if OLD_STYLE_ERRORS
+ prefix = "[ERROR]: ";
+ style = error_message_style;
+ prefix_len = 9;
+#else
+ popup->set_name ("ErrorMessage");
+ popup->set_text (str);
+ popup->touch ();
+ return;
+#endif
+ break;
+ case Transmitter::Info:
+#if OLD_STYLE_ERRORS
+ prefix = "[INFO]: ";
+ style = info_message_style;
+ prefix_len = 8;
+#else
+ popup->set_name ("InfoMessage");
+ popup->set_text (str);
+ popup->touch ();
+ return;
+#endif
+
+ break;
+ case Transmitter::Warning:
+#if OLD_STYLE_ERRORS
+ prefix = "[WARNING]: ";
+ style = warning_message_style;
+ prefix_len = 11;
+#else
+ popup->set_name ("WarningMessage");
+ popup->set_text (str);
+ popup->touch ();
+ return;
+#endif
+ break;
+ default:
+ /* no choice but to use text/console output here */
+ cerr << "programmer error in UI::check_error_messages (channel = " << chn << ")\n";
+ ::exit (1);
+ }
+
+ errors->text().get_buffer()->begin_user_action();
+
+ if (fatal_received) {
+ handle_fatal (str);
+ } else {
+
+ display_message (prefix, prefix_len, style, str);
+
+ if (!errors->is_visible()) {
+ toggle_errors();
+ }
+ }
+
+ errors->text().get_buffer()->end_user_action();
+}
+
+void
+UI::toggle_errors ()
+{
+ if (!errors->is_visible()) {
+ errors->set_position (Gtk::WIN_POS_MOUSE);
+ errors->show ();
+ } else {
+ errors->hide ();
+ }
+}
+
+void
+UI::display_message (const char *prefix, gint prefix_len, Glib::RefPtr<Gtk::Style> style, const char *msg)
+{
+ Glib::RefPtr<Gtk::TextBuffer::Tag> ptag = Gtk::TextBuffer::Tag::create();
+ Glib::RefPtr<Gtk::TextBuffer::Tag> mtag = Gtk::TextBuffer::Tag::create();
+
+ Pango::FontDescription pfont(style->get_font());
+ ptag->property_font_desc().set_value(pfont);
+ ptag->property_foreground_gdk().set_value(style->get_fg(Gtk::STATE_ACTIVE));
+ ptag->property_background_gdk().set_value(style->get_bg(Gtk::STATE_ACTIVE));
+
+ Pango::FontDescription mfont (style->get_font());
+ mtag->property_font_desc().set_value(mfont);
+ mtag->property_foreground_gdk().set_value(style->get_fg(Gtk::STATE_NORMAL));
+ mtag->property_background_gdk().set_value(style->get_bg(Gtk::STATE_NORMAL));
+
+ Glib::RefPtr<Gtk::TextBuffer> buffer (errors->text().get_buffer());
+ buffer->insert_with_tag(buffer->end(), prefix, ptag);
+ buffer->insert_with_tag(buffer->end(), msg, mtag);
+ buffer->insert_with_tag(buffer->end(), "\n", mtag);
+
+ errors->scroll_to_bottom ();
+}
+
+void
+UI::handle_fatal (const char *message)
+{
+ Gtk::Window win (Gtk::WINDOW_POPUP);
+ Gtk::VBox packer;
+ Gtk::Label label (message);
+ Gtk::Button quit (_("Press To Exit"));
+
+ win.set_default_size (400, 100);
+
+ string title;
+ title = _ui_name;
+ title += ": Fatal Error";
+ win.set_title (title);
+
+ win.set_position (Gtk::WIN_POS_MOUSE);
+ win.add (packer);
+
+ packer.pack_start (label, true, true);
+ packer.pack_start (quit, false, false);
+ quit.signal_clicked().connect(mem_fun(*this,&UI::quit));
+
+ win.show_all ();
+ win.set_modal (true);
+
+ theMain->run ();
+
+ exit (1);
+}
+
+void
+UI::popup_error (const char *text)
+{
+ PopUp *pup;
+
+ if (!caller_is_gui_thread()) {
+ error << "non-UI threads can't use UI::popup_error"
+ << endmsg;
+ return;
+ }
+
+ pup = new PopUp (Gtk::WIN_POS_MOUSE, 0, true);
+ pup->set_text (text);
+ pup->touch ();
+}
+
+
+void
+UI::flush_pending ()
+{
+ if (!caller_is_gui_thread()) {
+ error << "non-UI threads cannot call UI::flush_pending()"
+ << endmsg;
+ return;
+ }
+
+ gtk_main_iteration();
+
+ while (gtk_events_pending()) {
+ gtk_main_iteration();
+ }
+}
+
+bool
+UI::just_hide_it (GdkEventAny *ev, Gtk::Window *win)
+{
+ win->hide_all ();
+ return true;
+}
+
+Gdk::Color
+UI::get_color (const string& prompt, bool& picked, Gdk::Color* initial)
+{
+ Gdk::Color color;
+
+ Gtk::ColorSelectionDialog color_dialog (prompt);
+
+ color_dialog.set_modal (true);
+ color_dialog.get_cancel_button()->signal_clicked().connect (bind (mem_fun (*this, &UI::color_selection_done), false));
+ color_dialog.get_ok_button()->signal_clicked().connect (bind (mem_fun (*this, &UI::color_selection_done), true));
+ color_dialog.signal_delete_event().connect (mem_fun (*this, &UI::color_selection_deleted));
+
+ if (initial) {
+ color_dialog.get_colorsel()->set_current_color (*initial);
+ }
+
+ color_dialog.show_all ();
+ color_picked = false;
+ picked = false;
+
+ Gtk::Main::run();
+
+ color_dialog.hide_all ();
+
+ if (color_picked) {
+ Gdk::Color f_rgba = color_dialog.get_colorsel()->get_current_color ();
+ color.set_red(f_rgba.get_red());
+ color.set_green(f_rgba.get_green());
+ color.set_blue(f_rgba.get_blue());
+
+ picked = true;
+ }
+
+ return color;
+}
+
+void
+UI::color_selection_done (bool status)
+{
+ color_picked = status;
+ Gtk::Main::quit ();
+}
+
+bool
+UI::color_selection_deleted (GdkEventAny *ev)
+{
+ Gtk::Main::quit ();
+ return true;
+}
diff --git a/libs/gtkmm2ext/gtkmm2ext-config.in b/libs/gtkmm2ext/gtkmm2ext-config.in
new file mode 100644
index 0000000000..2744b20c52
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext-config.in
@@ -0,0 +1,232 @@
+#!/bin/sh
+
+af_libs=
+af_cflags=
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+
+##
+## Define usage()
+##
+usage()
+{
+ cat <<EOF
+Usage: pbd-config [OPTIONS] [LIBRARIES]
+Options:
+ --cflags print pre-processor and compiler flags
+ --libs print library linking information
+ --libs-dirs only print the -L/-R part of --libs
+ --libs-names only print the -l part of --libs
+ --help display this help and exit
+ --macros print the path to m4 macros
+
+ --prefix[=DIR]
+ --exec_prefix[=DIR]
+ --version output gtkmm2ext version information
+Libraries:
+ gtkmm2ext
+EOF
+ exit $1
+}
+
+##
+## Process options
+##
+parse()
+{
+# we must be called with at least one argument
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+# at least one option should be selected
+case "$1" in
+ --*)
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+esac
+
+# grab all -- arguments
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) af_optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) af_optarg= ;;
+ esac
+
+ case $1 in
+ --help)
+ usage 0 0>&2
+ ;;
+ --cflags)
+ af_echo_cflags=yes
+ ;;
+ --libs)
+ af_echo_libs_L=yes
+ af_echo_libs_l=yes
+ ;;
+ --libs-dirs)
+ af_echo_libs_L=yes
+ ;;
+ --libs-names)
+ af_echo_libs_l=yes
+ ;;
+ --macros*)
+
+echo -I @prefix@/include/gtkmm2ext/macros
+exit
+
+ ;;
+ --prefix=*)
+ prefix=$af_optarg
+ af_prefix_set=yes
+ ;;
+ --prefix)
+ af_echo_prefix=yes
+ ;;
+ --exec_prefix=*)
+ exec_prefix=$af_optarg
+ af_exec_prefix_set=yes
+ ;;
+ --exec_prefix)
+ af_echo_exec_prefix=yes
+ ;;
+ --version)
+ af_echo_version=yes
+ ;;
+ --*)
+ usage 1 1>&2
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+# if we have a default library use it
+if test $# -eq 0; then
+if test "X$af_lib_default" != "X"; then
+ af_lib__AF_LIB_DEFAULT=yes
+ return
+fi
+fi
+
+while test $# -gt 0; do
+ case $1 in
+ gtkmm2ext)
+ af_lib_gtkmm2ext=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+}
+
+print_result()
+{
+if test "X$af_echo_cflags" = "Xyes"; then
+ af_all_flags="$af_cflags"
+fi
+
+if test "X$af_echo_libs_L" = "Xyes" || test "X$af_echo_libs_l" = "Xyes"; then
+ af_all_flags="$af_all_flags $af_libs"
+fi
+
+if test -z "$af_all_flags" || test "X$af_all_flags" = "X "; then
+ exit 1
+fi
+
+# Straight out any possible duplicates, but be careful to
+# get `-lfoo -lbar -lbaz' for `-lfoo -lbaz -lbar -lbaz'
+af_other_flags=
+af_lib_L_flags=
+af_rev_libs=
+for i in $af_all_flags; do
+ case "$i" in
+ # a library, save it for later, in reverse order
+ -l*) af_rev_libs="$i $af_rev_libs" ;;
+ -L*|-R*)
+ if test "X$af_echo_libs_L" = "Xyes"; then
+ case " $af_lib_L_flags " in
+ *\ $i\ *) ;; # already there
+ *) af_lib_L_flags="$af_lib_L_flags $i" ;; # add it to output
+ esac
+ fi;;
+ *)
+ case " $af_other_flags " in
+ *\ $i\ *) ;; # already there
+ *) af_other_flags="$af_other_flags $i" ;; # add it to output
+ esac ;;
+ esac
+done
+
+af_ord_libs=
+if test "X$af_echo_libs_l" = "Xyes"; then
+ for i in $af_rev_libs; do
+ case " $af_ord_libs " in
+ *\ $i\ *) ;; # already there
+ *) af_ord_libs="$i $af_ord_libs" ;; # add it to output in reverse order
+ esac
+ done
+fi
+
+echo $af_other_flags $af_lib_L_flags $af_ord_libs
+}
+
+##
+## Main Body
+##
+
+parse $*
+
+
+##
+## Initialize names
+##
+
+
+
+
+
+if test "X$af_echo_prefix" = "Xyes"; then
+ echo $prefix
+fi
+
+if test "X$af_echo_exec_prefix" = "Xyes"; then
+ echo $exec_prefix
+fi
+
+if test "X$af_echo_version" = "Xyes"; then
+ echo @LIBGTKMMEXT_VERSION@
+ exit 0
+fi
+
+
+##
+## Libraries
+##
+
+#dummy because this should always be selected
+
+
+if test "@includedir@" != /usr/include ; then
+ includes="-I@includedir@"
+fi
+if test "@libdir@" != /usr/lib ; then
+ libs="-L@libdir@"
+fi
+af_cflags="$af_cflags $includes @GLIB_CFLAGS@ @GTK_CFLAGS@ @GTKMM_CFLAGS@ @SIGC_CFLAGS@ "
+af_libs="$libs -lgtkmm2ext @GLIB_LIBS@ @GTK_LIBS@ @GTKMM_LIBS@ @PBD_LIBS@ @SIGC_LIBS@ $af_libs"
+
+
+
+
+print_result
+
+exit 0
+
diff --git a/libs/gtkmm2ext/gtkmm2ext/.cvsignore b/libs/gtkmm2ext/gtkmm2ext/.cvsignore
new file mode 100644
index 0000000000..67020331ba
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/.cvsignore
@@ -0,0 +1 @@
+version.h
diff --git a/libs/gtkmm2ext/gtkmm2ext/auto_spin.h b/libs/gtkmm2ext/gtkmm2ext/auto_spin.h
new file mode 100644
index 0000000000..41d83373ce
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/auto_spin.h
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 2000 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_auto_spin_h__
+#define __gtkmm2ext_auto_spin_h__
+
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+
+class AutoSpin
+
+{
+ public:
+ AutoSpin (Gtk::Adjustment &adj, gfloat cr = 0);
+
+ Gtk::Adjustment &get_adjustment() { return adjustment; }
+
+ void use_left_as_decrement (bool yn) { left_is_decrement = yn; }
+ void set_wrap (bool yn) { wrap = yn; }
+ void set_climb_rate (gfloat cr) { climb_rate = cr; }
+ void set_bounds (gfloat initial, gfloat low, gfloat high,
+ bool with_reset = true);
+
+ gint button_press (GdkEventButton *);
+ gint stop_spinning (GdkEventButton *ignored_but_here_for_clicked);
+ void start_spinning (bool decrementing, bool use_page);
+
+ private:
+ Gtk::Adjustment &adjustment;
+ gfloat climb_rate;
+ gfloat timer_increment;
+ gfloat initial;
+ unsigned int timer_calls;
+ bool have_timer;
+ bool need_timer;
+ bool wrap;
+ gint timeout_tag;
+ bool left_is_decrement;
+
+ static const unsigned int initial_timer_interval;
+ static const unsigned int timer_interval;
+ static const unsigned int climb_timer_calls;
+
+ void stop_timer ();
+ static gint _timer (void *arg);
+ gint timer ();
+ bool adjust_value (gfloat increment);
+ void set_value (gfloat value);
+};
+
+} /* namespace */
+
+#endif /* __gtkmm2ext_auto_spin_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
new file mode 100644
index 0000000000..1a4b78009d
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2004 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_bar_controller_h__
+#define __gtkmm2ext_bar_controller_h__
+
+#include <gtkmm.h>
+#include <gtkmm2ext/popup.h>
+
+namespace MIDI {
+ class Controllable;
+}
+
+namespace Gtkmm2ext {
+
+class BarController : public Gtk::Frame
+{
+ public:
+ BarController (Gtk::Adjustment& adj, MIDI::Controllable*, sigc::slot<void,char*,unsigned int>);
+ virtual ~BarController () {}
+
+ void set_bind_button_state (guint button, guint statemask);
+ void get_bind_button_state (guint &button, guint &statemask);
+ void midicontrol_set_tip ();
+ void midi_learn ();
+
+ void set_sensitive (bool yn) {
+ darea.set_sensitive (yn);
+ }
+
+ enum Style {
+ LeftToRight,
+ RightToLeft,
+ Line,
+ CenterOut,
+ TopToBottom,
+ BottomToTop
+ };
+
+ Style style() const { return _style; }
+ void set_style (Style);
+ void set_with_text (bool yn);
+ void set_use_parent (bool yn);
+
+ Gtk::SpinButton& get_spin_button() { return spinner; }
+
+ sigc::signal<void> StartGesture;
+ sigc::signal<void> StopGesture;
+
+ /* export this to allow direct connection to button events */
+
+ Gtk::Widget& event_widget() { return darea; }
+
+ protected:
+ Gtk::Adjustment& adjustment;
+ Gtk::DrawingArea darea;
+ Gtkmm2ext::PopUp prompter;
+ MIDI::Controllable* midi_control;
+ sigc::slot<void,char*,unsigned int> label_callback;
+ Style _style;
+ bool grabbed;
+ bool switching;
+ bool switch_on_release;
+ bool with_text;
+ double initial_value;
+ double grab_x;
+ GdkWindow* grab_window;
+ Gtk::SpinButton spinner;
+ bool use_parent;
+
+ guint bind_button;
+ guint bind_statemask;
+ bool prompting, unprompting;
+
+ gint button_press (GdkEventButton *);
+ gint button_release (GdkEventButton *);
+ gint motion (GdkEventMotion *);
+ gint expose (GdkEventExpose *);
+
+ gint mouse_control (double x, GdkWindow* w, double scaling);
+
+ gint prompter_hiding (GdkEventAny *);
+ void midicontrol_prompt ();
+ void midicontrol_unprompt ();
+ void update_midi_control ();
+
+ gint switch_to_bar ();
+ gint switch_to_spinner ();
+
+ void entry_activated ();
+ gint entry_focus_out (GdkEventFocus*);
+};
+
+
+}; /* namespace */
+
+#endif // __gtkmm2ext_bar_controller_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h
new file mode 100644
index 0000000000..1e460b3790
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_gtkmm_bindable_button_h__
+#define __pbd_gtkmm_bindable_button_h__
+
+#include <gtkmm.h>
+#include <gtkmm2ext/popup.h>
+
+
+namespace MIDI {
+ class Controllable;
+}
+
+
+namespace Gtkmm2ext {
+
+class BindableToggleButton : public Gtk::ToggleButton
+{
+ public:
+ BindableToggleButton(MIDI::Controllable *);
+
+ //: Create a check button with a label.
+ //- You won't be able
+ //- to add a widget in this button since it already has a {\class Gtk_Label}
+ //- in it.
+ explicit BindableToggleButton(MIDI::Controllable *, const string &label);
+
+ virtual ~BindableToggleButton() {}
+
+ void set_bind_button_state (guint button, guint statemask);
+ void get_bind_button_state (guint &button, guint &statemask);
+
+ void midicontrol_set_tip ();
+
+ void midi_learn ();
+
+ protected:
+
+ Gtkmm2ext::PopUp prompter;
+
+ MIDI::Controllable* midi_control;
+
+ guint bind_button;
+ guint bind_statemask;
+
+ bool prompting, unprompting;
+
+ void init_events ();
+ gint button_press (GdkEventButton *);
+ gint prompter_hiding (GdkEventAny *);
+ void midicontrol_prompt ();
+ void midicontrol_unprompt ();
+
+
+};
+
+};
+
+#endif
diff --git a/libs/gtkmm2ext/gtkmm2ext/choice.h b/libs/gtkmm2ext/gtkmm2ext/choice.h
new file mode 100644
index 0000000000..4b8baede52
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/choice.h
@@ -0,0 +1,44 @@
+#ifndef __pbd_gtkmm_choice_h__
+#define __pbd_gtkmm_choice_h__
+
+#include <gtkmm.h>
+#include <vector>
+
+namespace Gtkmm2ext {
+
+class Choice : public Gtk::Window
+{
+ public:
+ Choice (std::string prompt, std::vector<std::string> choices);
+ virtual ~Choice ();
+
+ /* This signal will be raised when a choice
+ is made or the choice window is deleted.
+ If the choice was to cancel, or the window
+ was deleted, then the argument will be -1.
+ Otherwise, it will be choice selected
+ of those presented, starting at zero.
+ */
+
+ sigc::signal<void,int> choice_made;
+ sigc::signal<void> chosen;
+
+ int get_choice ();
+
+ protected:
+ void on_realize ();
+
+ private:
+ Gtk::VBox packer;
+ Gtk::Label prompt_label;
+ Gtk::HBox button_packer;
+ std::vector<Gtk::Button*> buttons;
+ int which_choice;
+
+ void _choice_made (int nbutton);
+ gint closed (GdkEventAny *);
+};
+
+} /* namespace */
+
+#endif // __pbd_gtkmm_choice_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/click_box.h b/libs/gtkmm2ext/gtkmm2ext/click_box.h
new file mode 100644
index 0000000000..cc35afb6e1
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/click_box.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_click_box_h__
+#define __gtkmm2ext_click_box_h__
+
+#include <string>
+#include <gtkmm.h>
+
+#include <gtkmm2ext/auto_spin.h>
+
+namespace Gtkmm2ext {
+
+class ClickBox : public Gtk::DrawingArea, public AutoSpin
+{
+ public:
+ ClickBox (Gtk::Adjustment *adj, const std::string &name);
+ ~ClickBox ();
+
+ void set_print_func(void (*pf)(char buf[32], Gtk::Adjustment &, void *),
+ void *arg) {
+ print_func = pf;
+ print_arg = arg;
+ set_label ();
+ }
+
+
+ protected:
+ bool on_expose_event (GdkEventExpose*);
+
+ private:
+ void (*print_func) (char buf[32], Gtk::Adjustment &, void *);
+ void *print_arg;
+
+ void set_label ();
+ bool button_press_handler (GdkEventButton *);
+ bool button_release_handler (GdkEventButton *);
+
+ static void default_printer (char buf[32], Gtk::Adjustment &, void *);
+};
+
+} /* namespace */
+
+#endif /* __gtkmm2ext_click_box_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/controller.h b/libs/gtkmm2ext/gtkmm2ext/controller.h
new file mode 100644
index 0000000000..b72f6c7ed7
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/controller.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 1998-99 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_controller_h__
+#define __gtkmm2ext_controller_h__
+
+#include <gtkmm.h>
+#include <gtkmm2ext/popup.h>
+#include <midi++/controllable.h>
+
+namespace Gtkmm2ext {
+
+class Controller : public MIDI::Controllable
+
+{
+ public:
+ Controller (Gtk::Adjustment *, MIDI::Port *);
+ virtual ~Controller () {}
+
+ void set_value (float);
+ float lower () { return adjustment->get_lower(); }
+ float upper () { return adjustment->get_upper(); }
+ float range () { return upper() - lower() /* XXX +1 ??? */ ; }
+
+ void midicontrol_prompt ();
+ void midicontrol_unprompt ();
+
+ protected:
+ Gtk::Adjustment *adjustment;
+
+ private:
+ Gtkmm2ext::PopUp prompter;
+ gfloat new_value;
+ bool new_value_pending;
+
+ static gint update_controller_value (void *);
+};
+
+}; /* namespace */
+
+#endif // __gtkmm2ext_controller_h__
+
+
diff --git a/libs/gtkmm2ext/gtkmm2ext/doi.h b/libs/gtkmm2ext/gtkmm2ext/doi.h
new file mode 100644
index 0000000000..f804c8a090
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/doi.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_doi_h__
+#define __ardour_gtk_doi_h__
+
+#include <gtkmm.h>
+
+/* XXX g++ 2.95 can't compile this as pair of member function templates */
+
+template<class T> gint idle_delete (T *obj) { delete obj; return FALSE; }
+template<class T> void delete_when_idle (T *obj) {
+ Gtk::Main::idle.connect (sigc::bind (sigc::slot (idle_delete<T>), obj));
+}
+template<class T> gint delete_on_unmap (GdkEventAny *ignored, T *obj) {
+ Gtk::Main::idle.connect (sigc::bind (sigc::slot (idle_delete<T>), obj));
+ return FALSE;
+}
+
+#endif /* __ardour_gtk_doi_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h
new file mode 100644
index 0000000000..5620a17a4d
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_fastmeter_h__
+#define __gtkmm2ext_fastmeter_h__
+
+#include <gtkmm/drawingarea.h>
+#include <gdkmm/pixmap.h>
+
+namespace Gtkmm2ext {
+
+class FastMeter : public Gtk::DrawingArea {
+ public:
+ enum Orientation {
+ Horizontal,
+ Vertical
+ };
+
+ FastMeter (long hold_cnt, unsigned long width, Orientation);
+ virtual ~FastMeter ();
+
+ void set (float level, float user_level=0.0f);
+ void clear ();
+
+ float get_level() { return current_level; }
+ float get_user_level() { return current_user_level; }
+ float get_peak() { return current_peak; }
+
+ long hold_count() { return hold_cnt; }
+ void set_hold_count (long);
+
+ static void set_horizontal_xpm (const char **xpm);
+ static void set_vertical_xpm (const char **xpm);
+
+ protected:
+ bool on_expose_event (GdkEventExpose*);
+ void on_size_request (GtkRequisition*);
+
+ private:
+ static Glib::RefPtr<Gdk::Pixmap>* h_pixmap;
+ static Glib::RefPtr<Gdk::Bitmap>* h_mask;
+ static gint h_pixheight;
+ static gint h_pixwidth;
+
+ static Glib::RefPtr<Gdk::Pixmap>* v_pixmap;
+ static Glib::RefPtr<Gdk::Bitmap>* v_mask;
+ static gint v_pixheight;
+ static gint v_pixwidth;
+
+ Orientation orientation;
+ Glib::RefPtr<Gdk::Pixmap>* backing;
+ Gdk::Rectangle pixrect;
+ gint request_width;
+ gint request_height;
+ unsigned long hold_cnt;
+ unsigned long hold_state;
+ float current_level;
+ float current_peak;
+ float current_user_level;
+
+ bool vertical_expose (GdkEventExpose*);
+ bool horizontal_expose (GdkEventExpose*);
+};
+
+
+} /* namespace */
+
+ #endif /* __gtkmm2ext_fastmeter_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
new file mode 100644
index 0000000000..147daa2623
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
@@ -0,0 +1,219 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_gtk_ui_h__
+#define __pbd_gtk_ui_h__
+
+#include <string>
+#include <queue>
+#include <map>
+
+#include <pthread.h>
+#include <gtkmm.h>
+#include <pbd/abstract_ui.h>
+#include <pbd/ringbufferNPT.h>
+#include <pbd/atomic.h>
+#include <pbd/pool.h>
+#include <pbd/error.h>
+#include <pbd/lockmonitor.h>
+
+using std::string;
+using std::queue;
+
+class Touchable;
+
+namespace Gtkmm2ext {
+
+class TextViewer;
+
+class UI : public AbstractUI
+
+{
+ public:
+ UI (string name, int *argc, char **argv[], string rcfile);
+ virtual ~UI ();
+
+ static UI *instance() { return theGtkUI; }
+
+ /* Abstract UI interfaces */
+
+ bool running ();
+ void quit ();
+ void kill ();
+ int load_rcfile (string);
+ void request (RequestType);
+ void run (Receiver &old_receiver);
+ void call_slot (sigc::slot<void>);
+ void call_slot_locked (sigc::slot<void>);
+ void touch_display (Touchable *);
+ void receive (Transmitter::Channel, const char *);
+ void register_thread (pthread_t, string);
+
+ bool caller_is_gui_thread () {
+ return pthread_equal (gui_thread, pthread_self());
+ }
+
+ /* Gtk-UI specific interfaces */
+
+ void set_tip (Gtk::Widget *, const gchar *txt, const gchar *hlp = 0);
+ void set_state (Gtk::Widget *w, Gtk::StateType state);
+ void idle_add (int (*)(void *), void *);
+ void timeout_add (unsigned int, int (*)(void *), void *);
+ void popup_error (const char *text);
+ void flush_pending ();
+ void toggle_errors ();
+
+ template<class T> static bool idle_delete (T *obj) { delete obj; return false; }
+ template<class T> static void delete_when_idle (T *obj) {
+ Glib::signal_idle().connect (bind (slot (&UI::idle_delete<T>), obj));
+ }
+
+ Gdk::Color get_color (const string& prompt, bool& picked, Gdk::Color *initial = 0);
+
+ /* starting is sent just before we enter the main loop,
+ stopping just after we return from it (at the top level)
+ */
+
+ sigc::signal<void> starting;
+ sigc::signal<void> stopping;
+
+ static bool just_hide_it (GdkEventAny *, Gtk::Window *);
+
+ protected:
+ virtual void handle_fatal (const char *);
+ virtual void display_message (const char *prefix, gint prefix_len,
+ Glib::RefPtr<Gtk::Style> style, const char *msg);
+
+ /* stuff to invoke member functions in another
+ thread so that we can keep the GUI running.
+ */
+
+ template<class UI_CLASS> struct thread_arg {
+ UI_CLASS *ui;
+ void (UI_CLASS::*func)(void *);
+ void *arg;
+ };
+
+ template<class UI_CLASS> static void *start_other_thread (void *arg);
+ template<class UI_CLASS> void other_thread (void (UI_CLASS::*func)(void *), void *arg = 0);
+
+ private:
+ struct Request {
+
+ /* this once used anonymous unions to merge elements
+ that are never part of the same request. that makes
+ the creation of a legal copy constructor difficult
+ because of the semantics of the slot member.
+ */
+
+ RequestType type;
+ Touchable *display;
+ const char *msg;
+ Gtk::StateType new_state;
+ int (*function)(void *);
+ Gtk::Widget *widget;
+ Transmitter::Channel chn;
+ void *arg;
+ const char *msg2;
+ unsigned int timeout;
+ sigc::slot<void> slot;
+
+ /* this is for CallSlotLocked requests */
+
+ pthread_mutex_t slot_lock;
+ pthread_cond_t slot_cond;
+
+ Request ();
+ ~Request () {
+ if (type == ErrorMessage && msg) {
+ /* msg was strdup()'ed */
+ free ((char *)msg);
+ }
+ }
+ };
+
+ static UI *theGtkUI;
+ static pthread_t gui_thread;
+ bool _active;
+ string _ui_name;
+ Gtk::Main *theMain;
+ Gtk::Tooltips *tips;
+ TextViewer *errors;
+
+ /* error message display styles */
+
+ Glib::RefPtr<Gtk::Style> error_message_style;
+ Glib::RefPtr<Gtk::Style> info_message_style;
+ Glib::RefPtr<Gtk::Style> warning_message_style;
+ Glib::RefPtr<Gtk::Style> fatal_message_style;
+
+ int signal_pipe[2];
+ PBD::Lock request_buffer_map_lock;
+ typedef std::map<pthread_t,RingBufferNPT<Request>* > RequestBufferMap;
+ RequestBufferMap request_buffers;
+ Request* get_request(RequestType);
+ pthread_key_t thread_request_buffer_key;
+
+ int setup_signal_pipe ();
+
+ void handle_ui_requests ();
+ void do_request (Request *);
+ void send_request (Request *);
+ static void signal_pipe_callback (void *, gint, GdkInputCondition);
+ void process_error_message (Transmitter::Channel, const char *);
+ void do_quit ();
+
+ void color_selection_done (bool status);
+ bool color_selection_deleted (GdkEventAny *);
+ bool color_picked;
+};
+
+template<class UI_CLASS> void *
+UI::start_other_thread (void *arg)
+
+{
+ thread_arg<UI_CLASS> *ta = (thread_arg<UI_CLASS> *) arg;
+ (ta->ui->*ta->func)(ta->arg);
+ delete ta;
+ return 0;
+}
+
+template<class UI_CLASS> void
+UI::other_thread (void (UI_CLASS::*func)(void *), void *arg)
+
+{
+ pthread_t thread_id;
+ thread_arg<UI_CLASS> *ta = new thread_arg<UI_CLASS>;
+
+ ta->ui = dynamic_cast<UI_CLASS *> (this);
+ if (ta->ui == 0) {
+ error << "UI::other thread called illegally"
+ << endmsg;
+ return;
+ }
+ ta->func = func;
+ ta->arg = arg;
+ pthread_create (&thread_id, 0, start_other_thread, ta);
+}
+
+
+} /* namespace */
+
+#endif /* __pbd_gtk_ui_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/gtkutils.h b/libs/gtkmm2ext/gtkmm2ext/gtkutils.h
new file mode 100644
index 0000000000..ae60252e83
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/gtkutils.h
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkutils_h__
+#define __gtkutils_h__
+
+#include <string>
+
+void set_usize_to_display_given_text (Gtk::Widget& w,
+ const std::string& text,
+ gint hpadding = 0,
+ gint vpadding = 0);
+#endif /* __gtkutils_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/hexentry.h b/libs/gtkmm2ext/gtkmm2ext/hexentry.h
new file mode 100644
index 0000000000..785d6eef36
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/hexentry.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_hexentry_h__
+#define __gtkmm2ext_hexentry_h__
+
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+
+class HexEntry : public Gtk::Entry
+
+{
+ public:
+ /* Take a byte-level representation of a series of hexadecimal
+ values and use them to set the displayed text of the entry.
+ Eg. if hexbuf[0] = 0xff and hexbuf[1] = 0xa1 and buflen = 2,
+ then the text will be set to "ff a1".
+ */
+
+ void set_hex (unsigned char *hexbuf, unsigned int buflen);
+
+ /* puts byte-level representation of current entry text
+ into hexbuf, and returns number of bytes written there.
+
+ NOTE: this will release the existing memory pointed to
+ by hexbuf if buflen indicates that it is not long enough
+ to hold the new representation, and hexbuf is not zero.
+
+ If the returned length is zero, the contents of hexbuf
+ are undefined.
+ */
+
+ unsigned int get_hex (unsigned char *hexbuf, size_t buflen);
+
+ private:
+ bool on_key_press_event (GdkEventKey *);
+};
+
+} /* namespace */
+
+#endif /* __gtkmm2ext_hexentry_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/idle_adjustment.h b/libs/gtkmm2ext/gtkmm2ext/idle_adjustment.h
new file mode 100644
index 0000000000..48e1cc449c
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/idle_adjustment.h
@@ -0,0 +1,26 @@
+#ifndef __gtkmm2ext_idle_adjustment_h__
+#define __gtkmm2ext_idle_adjustment_h__
+
+#include <sys/time.h>
+#include <gtkmm/adjustment.h>
+
+namespace Gtkmm2ext {
+
+class IdleAdjustment : public sigc::trackable
+{
+ public:
+ IdleAdjustment (Gtk::Adjustment& adj);
+ ~IdleAdjustment ();
+
+ sigc::signal<void> value_changed;
+
+ private:
+ void underlying_adjustment_value_changed();
+ struct timeval last_vc;
+ gint timeout_handler();
+ bool timeout_queued;
+};
+
+}
+
+#endif /* __gtkmm2ext_idle_adjustment_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/pix.h b/libs/gtkmm2ext/gtkmm2ext/pix.h
new file mode 100644
index 0000000000..b06f6046ea
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/pix.h
@@ -0,0 +1,87 @@
+#ifndef __pbd_gtkmm_pix_h__
+#define __pbd_gtkmm_pix_h__
+
+#include <string>
+#include <map>
+#include <vector>
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+
+class Pix
+{
+ typedef std::map<std::string, Pix *> PixCache;
+ static PixCache *cache;
+
+ PixCache::iterator cache_position;
+ int refcnt;
+ bool generated;
+ std::vector<std::string *> *files;
+ std::vector<const char **> data;
+ bool from_files;
+ int pixmap_count;
+ int last_pixmap;
+ Glib::RefPtr<Gdk::Pixmap> *pixmaps;
+ Glib::RefPtr<Gdk::Bitmap> *bitmaps;
+ int max_pixwidth;
+ int max_pixheight;
+ bool _homegenous;
+
+ Pix (const std::string &dirpath, const std::string &regexp,
+ bool homogenous = true);
+ Pix (std::vector<const char **> xpm_data, bool homogenous = true);
+ virtual ~Pix();
+
+ friend Pix *get_pix (const std::string &dirpath,
+ const std::string &regexp,
+ bool homogenous);
+ friend Pix *get_pix (std::string name,
+ std::vector<const char **> xpm_data,
+ bool homogenous);
+ friend void finish_pix (Pix *);
+
+ public:
+ Pix (bool homogenous = true);
+
+ void generate ();
+ int n_pixmaps() { return pixmap_count; }
+ int max_pixmap() { return last_pixmap; }
+ bool homogenous () { return _homegenous; }
+
+ /* ref/unref should really be protected, but we don't know the
+ name of the class that should have access to them.
+ */
+
+ void ref () { refcnt++; }
+ void unref () { if (refcnt) refcnt--; }
+
+ Glib::RefPtr<Gdk::Bitmap>* shape_mask (int n) {
+ if (n < pixmap_count) {
+ return &bitmaps[n];
+ }
+ return 0;
+ }
+
+ Glib::RefPtr<Gdk::Pixmap>* pixmap(int n) {
+ if (n < pixmap_count) {
+ return &pixmaps[n];
+ }
+ return 0;
+ }
+
+ int max_width() { return max_pixwidth; }
+ int max_height() { return max_pixheight; }
+};
+
+extern Pix *get_pix (const std::string &dirpath,
+ const std::string &regexp,
+ bool homog = false);
+
+extern Pix *get_pix (std::string,
+ std::vector<const char **>,
+ bool homog = false);
+extern void finish_pix (Pix *);
+
+} /* namespace */
+
+#endif // __pbd_gtkmm_pix_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/pixscroller.h b/libs/gtkmm2ext/gtkmm2ext/pixscroller.h
new file mode 100644
index 0000000000..4501a0c88c
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/pixscroller.h
@@ -0,0 +1,47 @@
+#ifndef __gtkmm2ext_pixscroller_h__
+#define __gtkmm2ext_pixscroller_h__
+
+#include <gtkmm/drawingarea.h>
+#include <gtkmm/adjustment.h>
+#include <gdkmm.h>
+
+#include <gtkmm2ext/pix.h>
+
+namespace Gtkmm2ext {
+
+class PixScroller : public Gtk::DrawingArea
+{
+ public:
+ PixScroller(Gtk::Adjustment& adjustment, Pix&);
+
+
+ bool on_expose_event (GdkEventExpose*);
+ bool on_motion_notify_event (GdkEventMotion*);
+ bool on_button_press_event (GdkEventButton*);
+ bool on_button_release_event (GdkEventButton*);
+ void on_size_request (GtkRequisition*);
+
+ protected:
+ Gtk::Adjustment& adj;
+
+ private:
+ Glib::RefPtr<Gdk::Pixmap> rail;
+ Glib::RefPtr<Gdk::Pixmap> slider;
+ Glib::RefPtr<Gdk::Bitmap> rail_mask;
+ Glib::RefPtr<Gdk::Bitmap> slider_mask;
+ Gdk::Rectangle sliderrect;
+ Gdk::Rectangle railrect;
+ GdkWindow* grab_window;
+ double grab_y;
+ double grab_start;
+ int overall_height;
+ bool dragging;
+
+ float default_value;
+
+ void adjustment_changed ();
+};
+
+} // namespace
+
+#endif /* __gtkmm2ext_pixscroller_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/popup.h b/libs/gtkmm2ext/gtkmm2ext/popup.h
new file mode 100644
index 0000000000..5684230f56
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/popup.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qui_popup_h__
+#define __qui_popup_h__
+
+#include <string>
+#include <gtkmm.h>
+
+#include <pbd/touchable.h>
+
+namespace Gtkmm2ext {
+
+class PopUp : public Gtk::Window, public Touchable
+{
+ public:
+ PopUp (Gtk::WindowPosition pos, unsigned int show_for_msecs = 0,
+ bool delete_on_hide = false);
+ virtual ~PopUp ();
+ void touch ();
+ void remove ();
+ void set_text (std::string);
+ void set_name (std::string);
+ gint button_click (GdkEventButton *);
+
+ bool on_delete_event (GdkEventAny* );
+
+ private:
+ Gtk::Label label;
+ std::string my_text;
+ gint timeout;
+ static gint remove_prompt_timeout (void *);
+ bool delete_on_hide;
+ unsigned int popdown_time;
+
+};
+
+} /* namespace */
+
+#endif // __qui_popup_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/prompter.h b/libs/gtkmm2ext/gtkmm2ext/prompter.h
new file mode 100644
index 0000000000..5997cc8b24
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/prompter.h
@@ -0,0 +1,86 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_prompter_h__
+#define __gtkmm2ext_prompter_h__
+
+#include <string>
+#include <gtkmm.h>
+#include <sigc++/sigc++.h>
+
+namespace Gtkmm2ext {
+
+class Prompter : public Gtk::Window
+
+{
+ public:
+ Prompter (bool modal = false);
+ ~Prompter () {};
+
+ void set_prompt (std::string prompt) {
+ entryLabel.set_label (prompt);
+ }
+
+ void set_initial_text (std::string txt) {
+ entry.set_text (txt);
+ entry.select_region (0, entry.get_text_length());
+ }
+
+ void change_labels (std::string ok, std::string cancel);
+
+ enum PrompterStatus {
+ entered,
+ cancelled
+ };
+
+ PrompterStatus status;
+ void get_result (std::string &str);
+
+ /* the prompter will send a `done' signal when it is finished.
+ the "caller" can then check `status' and if it wants to
+ can then call `get_result()'.
+ */
+
+ sigc::signal<void> done;
+
+ protected:
+ Gtk::Entry& the_entry() { return entry; }
+
+ private:
+ Gtk::VBox packer;
+ Gtk::HBox buttonBox;
+ Gtk::Entry entry;
+ Gtk::VBox entryBox;
+ Gtk::Label entryLabel;
+ Gtk::Button ok;
+ Gtk::Button cancel;
+
+ void activated ();
+ void cancel_click ();
+
+ bool deleted (GdkEventAny *);
+
+ void on_realize ();
+ void on_map ();
+};
+
+} /* namespace */
+
+#endif /* __gtkmm2ext_prompter_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/selector.h b/libs/gtkmm2ext/gtkmm2ext/selector.h
new file mode 100644
index 0000000000..f84c85cb4c
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/selector.h
@@ -0,0 +1,103 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkselector_h__
+#define __gtkselector_h__
+
+#include <string>
+#include <vector>
+
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+
+class TreeView_Selector : public Gtk::TreeView
+{
+public:
+ TreeView_Selector() {}
+ virtual ~TreeView_Selector() {}
+
+protected:
+ virtual bool on_button_press_event(GdkEventButton *ev);
+};
+
+typedef void (SelectorRefillFunction)(Glib::RefPtr<Gtk::ListStore>, void *);
+
+class Selector : public Gtk::VBox
+{
+ friend class Gtkmm2ext::TreeView_Selector;
+
+public:
+ Selector (SelectorRefillFunction, void *arg,
+ std::vector<std::string> titles);
+
+ virtual ~Selector ();
+ Glib::RefPtr<Gtk::ListStore> liststore () { return lstore; }
+ void reset (void (*refiller)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg);
+ void set_size (unsigned int w, unsigned int h) {
+ scroll.set_size_request (w, h);
+ tview.columns_autosize ();
+ }
+
+ /* selection is activated via a double click, choice via
+ a single click.
+ */
+ sigc::signal<void,Gtk::TreeView&, Glib::RefPtr<Gtk::TreeSelection> > selection_made;
+ sigc::signal<void,Gtk::TreeView&, Glib::RefPtr<Gtk::TreeSelection> > choice_made;
+ sigc::signal<void,Gtk::TreeView&, Glib::RefPtr<Gtk::TreeSelection> > shift_made;
+ sigc::signal<void,Gtk::TreeView&, Glib::RefPtr<Gtk::TreeSelection> > control_made;
+
+ sigc::signal<void> update_contents;
+
+ void accept();
+ void cancel();
+ void rescan();
+
+
+ protected:
+ virtual void on_map ();
+ virtual void on_show ();
+
+ private:
+ Gtk::ScrolledWindow scroll;
+ Gtk::TreeModel::ColumnRecord column_records;
+ Glib::RefPtr<Gtk::ListStore> lstore;
+ Gtkmm2ext::TreeView_Selector tview;
+ void (*refiller)(Glib::RefPtr<Gtk::ListStore>, void *);
+ void *refill_arg;
+ gint selected_row;
+ gint selected_column;
+ gint chosen_row;
+ gint chosen_column;
+
+ void refill ();
+ void chosen ();
+ void shift_clicked ();
+ void control_clicked ();
+
+ static gint _accept (gpointer);
+ static gint _chosen (gpointer);
+ static gint _shift_clicked (gpointer);
+ static gint _control_clicked (gpointer);
+
+};
+
+} /* namespace */
+
+#endif // __gtkselector_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h
new file mode 100644
index 0000000000..3cb8e9d363
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h
@@ -0,0 +1,98 @@
+/*
+ Copyright (C) 1998-99 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_motion_controller_h__
+#define __gtkmm2ext_motion_controller_h__
+
+#include <gtkmm.h>
+#include <gtkmm2ext/popup.h>
+#include <gtkmm2ext/pixscroller.h>
+
+namespace Gtkmm2ext {
+ class Pix;
+}
+
+namespace MIDI {
+ class Controllable;
+}
+
+namespace Gtkmm2ext {
+
+class SliderController : public Gtkmm2ext::PixScroller
+{
+ public:
+ SliderController (Gtkmm2ext::Pix* pixset,
+ Gtk::Adjustment* adj,
+ MIDI::Controllable*,
+ bool with_numeric = true);
+
+ virtual ~SliderController () {}
+
+ void set_bind_button_state (guint button, guint statemask);
+ void get_bind_button_state (guint &button, guint &statemask);
+ void midicontrol_set_tip ();
+ void midi_learn ();
+
+ void set_value (float);
+ // void set_sensitive (bool yn) {
+ // spin.set_sensitive (yn);
+ // }
+
+ Gtk::SpinButton & get_spin_button () { return spin; }
+
+ protected:
+ Gtk::SpinButton spin;
+ Gtk::Frame spin_frame;
+ Gtk::HBox spin_hbox;
+ Gtkmm2ext::PopUp prompter;
+ MIDI::Controllable* midi_control;
+
+ guint bind_button;
+ guint bind_statemask;
+ bool prompting, unprompting;
+
+ bool button_press (GdkEventButton *);
+ bool prompter_hiding (GdkEventAny *);
+ void midicontrol_prompt ();
+ void midicontrol_unprompt ();
+ void update_midi_control ();
+};
+
+class VSliderController : public SliderController
+{
+ public:
+ VSliderController (Gtkmm2ext::Pix *pixset,
+ Gtk::Adjustment *adj,
+ MIDI::Controllable *,
+ bool with_numeric = true);
+};
+
+class HSliderController : public SliderController
+{
+ public:
+ HSliderController (Gtkmm2ext::Pix *pixset,
+ Gtk::Adjustment *adj,
+ MIDI::Controllable *,
+ bool with_numeric = true);
+};
+
+
+}; /* namespace */
+
+#endif // __gtkmm2ext_motion_controller_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/stop_signal.h b/libs/gtkmm2ext/gtkmm2ext/stop_signal.h
new file mode 100644
index 0000000000..2890efecfb
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/stop_signal.h
@@ -0,0 +1,14 @@
+#ifndef __ardour_gtk_stop_signal_h__
+#define __ardour_gtk_stop_signal_h__
+
+#include <gtk--/widget.h>
+#include <gtk/gtksignal.h>
+
+static inline gint
+stop_signal (Gtk::Widget& widget, const char *signal_name)
+{
+ gtk_signal_emit_stop_by_name (GTK_OBJECT(widget.gtkobj()), signal_name);
+ return TRUE;
+}
+
+#endif /* __ardour_gtk_stop_signal_h__ */
diff --git a/libs/gtkmm2ext/gtkmm2ext/tearoff.h b/libs/gtkmm2ext/gtkmm2ext/tearoff.h
new file mode 100644
index 0000000000..d0478d5c57
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/tearoff.h
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2003 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_tearoff_h__
+#define __gtkmm2ext_tearoff_h__
+
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+
+class TearOff : public Gtk::HBox
+{
+ public:
+ TearOff (Gtk::Widget& contents);
+ virtual ~TearOff ();
+
+ sigc::signal<void> Detach;
+ sigc::signal<void> Attach;
+
+ Gtk::Window* tearoff_window() const { return own_window; }
+ bool torn_off() const;
+
+ private:
+ Gtk::Widget& contents;
+ Gtk::Window* own_window;
+ Gtk::Arrow tearoff_arrow;
+ Gtk::Arrow close_arrow;
+ Gtk::HBox window_box;
+ Gtk::EventBox tearoff_event_box;
+ Gtk::EventBox close_event_box;
+ double drag_x;
+ double drag_y;
+ bool dragging;
+
+ gint tearoff_click (GdkEventButton*);
+ gint close_click (GdkEventButton*);
+
+ gint window_motion (GdkEventMotion*);
+ gint window_button_press (GdkEventButton*);
+ gint window_button_release (GdkEventButton*);
+ gint window_delete_event (GdkEventAny*);
+};
+
+} /* namespace */
+
+#endif // __gtkmm2ext_tearoff_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/textviewer.h b/libs/gtkmm2ext/gtkmm2ext/textviewer.h
new file mode 100644
index 0000000000..280eb4437d
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/textviewer.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_gtkmm_textviewer_h__
+#define __pbd_gtkmm_textviewer_h__
+
+#include <string>
+#include <gtkmm.h>
+
+#include <pbd/transmitter.h>
+
+using std::string;
+
+namespace Gtkmm2ext {
+
+class TextViewer : public Gtk::Window, public Transmitter
+{
+ Gtk::TextView etext;
+ Gtk::VBox vbox1;
+ Gtk::VBox vbox2;
+ Gtk::ScrolledWindow scrollwin;
+ Gtk::Button dismiss;
+ bool _editable;
+
+ void toggle_edit ();
+ void toggle_word_wrap ();
+ void signal_released_handler ();
+
+ public:
+ TextViewer (size_t width, size_t height);
+ Gtk::TextView& text() { return etext; }
+ Gtk::Button& dismiss_button() { return dismiss; }
+
+ void insert_file (const string &);
+ void scroll_to_bottom ();
+
+ void deliver ();
+};
+
+} /* namespace */
+
+#endif // __pbd_gtkmm_textviewer_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/utils.h b/libs/gtkmm2ext/gtkmm2ext/utils.h
new file mode 100644
index 0000000000..867f9ed904
--- /dev/null
+++ b/libs/gtkmm2ext/gtkmm2ext/utils.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmm2ext_utils_h__
+#define __gtkmm2ext_utils_h__
+
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+ void init ();
+
+ void set_usize_to_display_given_text (Gtk::Widget &w,
+ const gchar *text,
+ gint hpadding,
+ gint vpadding);
+
+ template<class T> void deferred_delete (void *ptr) {
+ delete static_cast<T *> (ptr);
+ }
+};
+
+gint do_not_propagate (GdkEventButton*);
+
+#endif /* __gtkmm2ext_utils_h__ */
diff --git a/libs/gtkmm2ext/gtkutils.cc b/libs/gtkmm2ext/gtkutils.cc
new file mode 100644
index 0000000000..a4e86b0a22
--- /dev/null
+++ b/libs/gtkmm2ext/gtkutils.cc
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+
+#include <gtkmm.h>
+#include <gtkmm2ext/gtkutils.h>
+
+void
+set_usize_to_display_given_text (Gtk::Widget &w,
+ const std::string& text,
+ gint hpadding,
+ gint vpadding)
+{
+ int height = 0;
+ int width = 0;
+
+ w.create_pango_layout(text)->get_pixel_size(width, height);
+
+ height += vpadding;
+ width += hpadding;
+
+ w.set_size_request(width, height);
+}
diff --git a/libs/gtkmm2ext/hexentry.cc b/libs/gtkmm2ext/hexentry.cc
new file mode 100644
index 0000000000..9862cac435
--- /dev/null
+++ b/libs/gtkmm2ext/hexentry.cc
@@ -0,0 +1,111 @@
+/*
+ Copyright (C) 2000 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <stdio.h> /* for sprintf, sigh ... */
+#include <string>
+#include <ctype.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtkmm2ext/hexentry.h>
+
+using namespace std;
+using namespace Gtkmm2ext;
+
+bool
+HexEntry::on_key_press_event (GdkEventKey *ev)
+
+{
+ if ((ev->keyval >= GDK_a && ev->keyval <= GDK_f) ||
+ (ev->keyval >= GDK_A && ev->keyval <= GDK_A) ||
+ (ev->keyval >= GDK_0 && ev->keyval <= GDK_9) ||
+ ev->keyval == GDK_space ||
+ ev->keyval == GDK_Tab ||
+ ev->keyval == GDK_Return ||
+ ev->keyval == GDK_BackSpace ||
+ ev->keyval == GDK_Delete) {
+ return Gtk::Entry::on_key_press_event (ev);
+ } else {
+ gdk_beep ();
+ return FALSE;
+ }
+}
+
+
+void
+HexEntry::set_hex (unsigned char *msg, unsigned int len)
+
+{
+ /* create a textual representation of the MIDI message */
+
+ if (msg && len) {
+ char *rep;
+
+ rep = new char[(len * 3) + 1];
+ for (size_t i = 0; i < len; i++) {
+ sprintf (&rep[i*3], "%02x ", msg[i]);
+ }
+ rep[len * 3] = '\0';
+ set_text (rep);
+ delete [] rep;
+ } else {
+ set_text ("");
+ }
+}
+
+unsigned int
+HexEntry::get_hex (unsigned char *hexbuf, size_t buflen)
+
+{
+ int fetched_len;
+ char buf[3];
+ string text = get_text();
+ string::size_type length = text.length ();
+ string::size_type offset;
+
+ fetched_len = 0;
+ buf[2] = '\0';
+ offset = 0;
+
+ while (1) {
+ offset = text.find_first_of ("abcdef0123456789", offset);
+
+ if (offset == string::npos) {
+ break;
+ }
+
+ /* grab two characters, but no more */
+
+ buf[0] = text[offset];
+
+ if (offset < length - 1) {
+ buf[1] = text[offset+1];
+ offset += 2;
+ } else {
+ buf[1] = '\0';
+ offset += 1;
+ }
+
+ hexbuf[fetched_len++] = (char) strtol (buf, 0, 16);
+ }
+
+ return fetched_len;
+}
+
+
diff --git a/libs/gtkmm2ext/i18n.h b/libs/gtkmm2ext/i18n.h
new file mode 100644
index 0000000000..7c79d2eb53
--- /dev/null
+++ b/libs/gtkmm2ext/i18n.h
@@ -0,0 +1,11 @@
+#ifndef __i18n_h__
+#define __i18n_h__
+
+#include <pbd/compose.h>
+#include "gettext.h"
+
+#define _(Text) dgettext (PACKAGE, Text)
+#define N_(Text) gettext_noop (Text)
+#define X_(Text) (Text)
+
+#endif // __i18n_h__
diff --git a/libs/gtkmm2ext/idle_adjustment.cc b/libs/gtkmm2ext/idle_adjustment.cc
new file mode 100644
index 0000000000..45118283c5
--- /dev/null
+++ b/libs/gtkmm2ext/idle_adjustment.cc
@@ -0,0 +1,54 @@
+#define _BSD_SOURCE
+#include <gtkmm2ext/idle_adjustment.h>
+#include <gtkmm/main.h>
+#include <iostream>
+
+using namespace Gtk;
+using namespace sigc;
+using namespace Gtkmm2ext;
+
+IdleAdjustment::IdleAdjustment (Gtk::Adjustment& adj)
+{
+ adj.signal_value_changed().connect (mem_fun (*this, &IdleAdjustment::underlying_adjustment_value_changed));
+ timeout_queued = 0;
+ gettimeofday (&last_vc, 0);
+}
+
+IdleAdjustment::~IdleAdjustment ()
+{
+}
+
+void
+IdleAdjustment::underlying_adjustment_value_changed ()
+{
+ gettimeofday (&last_vc, 0);
+
+ if (timeout_queued) {
+ return;
+ }
+
+ Glib::signal_timeout().connect(mem_fun(*this, &IdleAdjustment::timeout_handler), 250);
+ timeout_queued = true;
+}
+
+gint
+IdleAdjustment::timeout_handler ()
+{
+ struct timeval now;
+ struct timeval tdiff;
+
+ gettimeofday (&now, 0);
+
+ timersub (&now, &last_vc, &tdiff);
+
+ std::cerr << "timer elapsed, diff = " << tdiff.tv_sec << " + " << tdiff.tv_usec << std::endl;
+
+ if (tdiff.tv_sec > 0 || tdiff.tv_usec > 250000) {
+ std::cerr << "send signal\n";
+ value_changed ();
+ timeout_queued = false;
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
diff --git a/libs/gtkmm2ext/libgtkmm2ext.pc.in b/libs/gtkmm2ext/libgtkmm2ext.pc.in
new file mode 100644
index 0000000000..ee87973e2b
--- /dev/null
+++ b/libs/gtkmm2ext/libgtkmm2ext.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gtkmm2ext
+
+Name: libgtkmm2ext
+Version: @VERSION@
+Description: libgtkmm2ext, a library of useful new C++ and C widgets for gtkmm users
+Requires: libpbd, libmidi++
+Libs: -L${libdir} -lgtkmm2ext @NON_PKG_LIBS@
+Cflags: -I${includedir} @NON_PKG_CFLAGS@
diff --git a/libs/gtkmm2ext/libgtkmm2ext.spec.in b/libs/gtkmm2ext/libgtkmm2ext.spec.in
new file mode 100644
index 0000000000..19657721ef
--- /dev/null
+++ b/libs/gtkmm2ext/libgtkmm2ext.spec.in
@@ -0,0 +1,68 @@
+Summary: extensions to the libgtkmm library
+%define lib_name gtkmm2ext
+Name: lib%{lib_name}
+Version: @VERSION@
+Release: 2
+Copyright: GPL
+Source: ftp://ftp.quasimodo.org/pub/libs/gtkmm2ext/current/%{name}-%{version}.tar.gz
+Url: http://www.quasimodo.org
+Vendor: Paul Barton Davis <pbd@op.net>
+Packager: jfm3 <jfm3@acm.org>
+Group: System Environment/Libraries
+Prefix: %{_prefix}
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+
+libgtkmm2ext provides extensions to Gtk-- useful for audio
+applications. These include ShapedWindow, MotionFeedback,
+PixmapButton and several more. It also includes the useful Pix class
+for managing sets of pixmaps, with reference counting etc.
+
+%prep
+%setup -q
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure $ARCH_FLAGS --prefix=%{prefix}
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d -m 755 $RPM_BUILD_ROOT%{prefix}/{{include,lib}/%{lib_name}}
+make install INSTALL="%(which install) -p" prefix=$RPM_BUILD_ROOT%{prefix}
+
+%post
+/sbin/ldconfig
+
+%postun
+/sbin/ldconfig
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README AUTHORS NEWS COPYING*
+%{prefix}/lib/libgtkmm2ext.so*
+
+%package devel
+Summary: extensions to the libgtkmm library -- developer package
+Group: System Environment/Libraries
+
+%description devel
+
+libgtkmm2ext provides extensions to Gtk-- useful for audio
+applications. These include ShapedWindow, MotionFeedback,
+PixmapButton and several more. It also includes the useful Pix class
+for managing sets of pixmaps, with reference counting etc.
+
+This package holds static libraries and headers needed by developers
+who wish to use libgtkmm2ext in their programs.
+
+%files devel
+%defattr(-,root,root)
+%{prefix}/include/gtkmm2ext/*
+%{prefix}/lib/libgtkmm2ext.a
+%{prefix}/lib/libgtkmm2ext.la
+%{prefix}/bin/gtkmm2ext-config
+%{prefix}/share/aclocal/gtkmm2ext.m4
diff --git a/libs/gtkmm2ext/pix.cc b/libs/gtkmm2ext/pix.cc
new file mode 100644
index 0000000000..c9f759b321
--- /dev/null
+++ b/libs/gtkmm2ext/pix.cc
@@ -0,0 +1,231 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <gdkmm.h>
+#include <gdkmm/pixmap.h>
+
+#include <pbd/pathscanner.h>
+#include <pbd/stl_delete.h>
+#include <pbd/failed_constructor.h>
+
+/* as of gcc 2.95.2, some of the stl_functors in this header are not
+ handled correctly. it sucks, but we put them inline here instead.
+
+ #include <pbd/stl_functors.h>
+*/
+
+#include <gtkmm2ext/pix.h>
+
+namespace std
+{
+ template<> struct less<string *> {
+ bool operator()(string *s1, string *s2) const {
+ return *s1 < *s2;
+ }
+ };
+}
+
+using namespace std;
+using namespace Gtkmm2ext;
+
+Pix::PixCache *Pix::cache;
+
+Pix::Pix (bool homog)
+
+{
+ pixmap_count = 0;
+ _homegenous = homog;
+}
+
+Pix::Pix (vector<const char **> xpm_data, bool homog)
+{
+ if (xpm_data.size() == 0) {
+ throw failed_constructor();
+ }
+
+ pixmap_count = xpm_data.size();
+ last_pixmap = pixmap_count - 1;
+ refcnt = 0;
+ generated = false;
+ max_pixwidth = 0;
+ max_pixheight = 0;
+ _homegenous = homog;
+
+ data = xpm_data;
+ from_files = false;
+
+ pixmaps = new Glib::RefPtr<Gdk::Pixmap> [pixmap_count];
+ bitmaps = new Glib::RefPtr<Gdk::Bitmap> [pixmap_count];
+ memset (pixmaps, 0, sizeof (Glib::RefPtr<Gdk::Pixmap>) * pixmap_count);
+ memset (bitmaps, 0, sizeof (Glib::RefPtr<Gdk::Bitmap>) * pixmap_count);
+}
+
+Pix::Pix (const string &dirpath, const string &regexp, bool homog)
+
+{
+ PathScanner scanner;
+ less<string *> cmp;
+
+ pixmap_count = 0;
+ last_pixmap = 0;
+ refcnt = 0;
+ generated = false;
+ max_pixwidth = 0;
+ max_pixheight = 0;
+ _homegenous = homog;
+
+ pixmaps = 0;
+ bitmaps = 0;
+
+ files = scanner (dirpath, regexp, false, true);
+
+ sort (files->begin(), files->end(), cmp);
+
+ if (files == 0) {
+ return;
+ }
+
+ /* create handy reference */
+
+ if ((pixmap_count = files->size()) == 0) {
+ return;
+ }
+
+ from_files = true;
+ pixmaps = new Glib::RefPtr<Gdk::Pixmap> [pixmap_count];
+ bitmaps = new Glib::RefPtr<Gdk::Bitmap> [pixmap_count];
+ memset (pixmaps, 0, sizeof (Glib::RefPtr<Gdk::Pixmap>) * pixmap_count);
+ memset (bitmaps, 0, sizeof (Glib::RefPtr<Gdk::Bitmap>) * pixmap_count);
+
+ last_pixmap = pixmap_count - 1;
+}
+
+Pix::~Pix ()
+
+{
+ if (from_files) {
+ vector_delete (files);
+ }
+
+ if (pixmap_count) delete [] pixmaps;
+ if (pixmap_count) delete [] bitmaps;
+}
+
+void
+Pix::generate ()
+
+{
+ if (generated) {
+ return;
+ }
+
+ for (int i = 0; i < pixmap_count; i++) {
+ if (from_files) {
+ string *strp;
+ strp = (*files)[i];
+ const char* str(strp->c_str());
+
+ pixmaps[i] = Gdk::Pixmap::create_from_xpm (Gdk::Colormap::get_system(),
+ bitmaps[i], &str);
+ } else {
+ gchar **xpm;
+ xpm = const_cast<gchar **> (data[i]);
+
+ pixmaps[i] = Gdk::Pixmap::create_from_xpm(Gdk::Colormap::get_system(),
+ bitmaps[i], Gdk::Color(), xpm);
+ }
+
+ int w, h;
+ pixmaps[i]->get_size(w, h);
+ if (w > max_pixwidth) max_pixwidth = w;
+ if (h > max_pixheight) max_pixheight = h;
+ }
+
+ generated = true;
+}
+
+Pix *
+Gtkmm2ext::get_pix (string name, vector<const char **> xpm_data, bool homog)
+{
+ Pix *ret = 0;
+ Pix::PixCache::iterator iter;
+ pair<string, Pix *> newpair;
+
+ if (Pix::cache == 0) {
+ Pix::cache = new Pix::PixCache;
+ }
+
+ if ((iter = Pix::cache->find (name)) == Pix::cache->end()) {
+ ret = new Pix (xpm_data, homog);
+ if (ret->pixmap_count == 0) {
+ delete ret;
+ return 0;
+ }
+ newpair.first = name;
+ newpair.second = ret;
+ ret->cache_position = (Pix::cache->insert (newpair)).first;
+ ret->refcnt++;
+ return ret;
+ } else {
+ (*iter).second->refcnt++;
+ return (*iter).second;
+ }
+}
+
+Pix *
+Gtkmm2ext::get_pix (const string &dirpath, const string &regexp, bool homog)
+{
+ Pix *ret = 0;
+ Pix::PixCache::iterator iter;
+ pair<string, Pix *> newpair;
+
+ if (Pix::cache == 0) {
+ Pix::cache = new Pix::PixCache;
+ }
+
+ if ((iter = Pix::cache->find (regexp)) == Pix::cache->end()) {
+ ret = new Pix (dirpath, regexp, homog);
+ if (ret->pixmap_count == 0) {
+ delete ret;
+ return 0;
+ }
+ newpair.first = regexp;
+ newpair.second = ret;
+ ret->cache_position = (Pix::cache->insert (newpair)).first;
+ ret->refcnt++;
+ return ret;
+ } else {
+ (*iter).second->refcnt++;
+ return (*iter).second;
+ }
+}
+
+void
+Gtkmm2ext::finish_pix (Pix *pix)
+
+{
+ pix->refcnt--;
+ if (pix->refcnt == 0) {
+ Pix::cache->erase (pix->cache_position);
+ delete pix;
+ }
+}
diff --git a/libs/gtkmm2ext/pixscroller.cc b/libs/gtkmm2ext/pixscroller.cc
new file mode 100644
index 0000000000..78f1725271
--- /dev/null
+++ b/libs/gtkmm2ext/pixscroller.cc
@@ -0,0 +1,248 @@
+/*
+ Copyright (C) 2005 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/pixscroller.h>
+
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+
+PixScroller::PixScroller (Adjustment& a, Pix& pix)
+ : adj (a)
+{
+ dragging = false;
+ add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
+
+ adj.signal_value_changed().connect (mem_fun (*this, &PixScroller::adjustment_changed));
+ default_value = adj.get_value();
+
+ pix.generate ();
+
+ rail = *(pix.pixmap (0));
+ rail_mask = *(pix.shape_mask (0));
+ slider = *(pix.pixmap (1));
+ slider_mask = *(pix.shape_mask (1));
+
+ int w, h;
+
+ slider->get_size (w, h);
+ sliderrect.set_width(w);
+ sliderrect.set_height(h);
+ rail->get_size (w, h);
+ railrect.set_width(w);
+ railrect.set_height(h);
+
+ railrect.set_y(sliderrect.get_height() / 2);
+ sliderrect.set_x(0);
+
+ overall_height = railrect.get_height() + sliderrect.get_height();
+
+ sliderrect.set_y((int) rint ((overall_height - sliderrect.get_height()) * (adj.get_upper() - adj.get_value())));
+ railrect.set_x((sliderrect.get_width() / 2) - 3);
+}
+
+void
+PixScroller::on_size_request (GtkRequisition* requisition)
+{
+ requisition->width = sliderrect.get_width();
+ requisition->height = overall_height;
+}
+
+bool
+PixScroller::on_expose_event (GdkEventExpose* ev)
+{
+ GdkRectangle intersect;
+ Glib::RefPtr<Gdk::Window> win (get_window());
+
+ win->draw_rectangle (get_style()->get_bg_gc(get_state()), TRUE,
+ ev->area.x,
+ ev->area.y,
+ ev->area.width,
+ ev->area.height);
+
+ if (gdk_rectangle_intersect (railrect.gobj(), &ev->area, &intersect)) {
+ Glib::RefPtr<Gdk::GC> gc(get_style()->get_bg_gc(get_state()));
+ win->draw_drawable (gc, rail,
+ intersect.x - railrect.get_x(),
+ intersect.y - railrect.get_y(),
+ intersect.x,
+ intersect.y,
+ intersect.width,
+ intersect.height);
+ }
+
+ if (gdk_rectangle_intersect (sliderrect.gobj(), &ev->area, &intersect)) {
+ Glib::RefPtr<Gdk::GC> gc(get_style()->get_fg_gc(get_state()));
+ Glib::RefPtr<Gdk::Bitmap> mask (slider_mask);
+// Do these have a gtk2 equivalent?
+// Gdk::GCValues values;
+// gc->get_values(values);
+ gc->set_clip_origin (sliderrect.get_x(), sliderrect.get_y());
+ gc->set_clip_mask (mask);
+ win->draw_drawable (gc, slider,
+ intersect.x - sliderrect.get_x(),
+ intersect.y - sliderrect.get_y(),
+ intersect.x,
+ intersect.y,
+ intersect.width,
+ intersect.height);
+// gc->set_clip_origin(values.clip_x_origin, values.clip_y_origin);
+// Gdk::Bitmap i_hate_gdk (values.clip_mask);
+// gc->set_clip_mask (i_hate_gdk);
+ }
+
+
+ return true;
+}
+
+bool
+PixScroller::on_button_press_event (GdkEventButton* ev)
+{
+ switch (ev->button) {
+ case 1:
+ if (!(ev->state & Gdk::SHIFT_MASK)) {
+ add_modal_grab();
+ grab_y = ev->y;
+ grab_start = ev->y;
+ grab_window = ev->window;
+ dragging = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ return false;
+}
+
+bool
+PixScroller::on_button_release_event (GdkEventButton* ev)
+{
+ double scale;
+
+ if (ev->state & GDK_CONTROL_MASK) {
+ if (ev->state & GDK_MOD1_MASK) {
+ scale = 0.05;
+ } else {
+ scale = 0.1;
+ }
+ } else {
+ scale = 1.0;
+ }
+
+ switch (ev->button) {
+ case 1:
+ if (dragging) {
+ remove_modal_grab();
+ dragging = false;
+
+ if (ev->y == grab_start) {
+ /* no motion - just a click */
+ double fract;
+
+ if (ev->y < sliderrect.get_height()/2) {
+ /* near the top */
+ fract = 1.0;
+ } else {
+ fract = 1.0 - (ev->y - sliderrect.get_height()/2) / railrect.get_height();
+ }
+
+ fract = min (1.0, fract);
+ fract = max (0.0, fract);
+
+ adj.set_value (scale * fract * (adj.get_upper() - adj.get_lower()));
+ }
+ } else {
+ if (ev->state & Gdk::SHIFT_MASK) {
+ adj.set_value (default_value);
+ cerr << "default value = " << default_value << endl;
+ }
+ }
+ break;
+ case 4:
+ /* wheel up */
+ adj.set_value (adj.get_value() + (adj.get_page_increment() * scale));
+ break;
+ case 5:
+ /* wheel down */
+ adj.set_value (adj.get_value() - (adj.get_page_increment() * scale));
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool
+PixScroller::on_motion_notify_event (GdkEventMotion* ev)
+{
+ if (dragging) {
+ double fract;
+ double delta;
+ double scale;
+
+ if (ev->window != grab_window) {
+ grab_y = ev->y;
+ grab_window = ev->window;
+ return true;
+ }
+
+ if (ev->state & GDK_CONTROL_MASK) {
+ if (ev->state & GDK_MOD1_MASK) {
+ scale = 0.05;
+ } else {
+ scale = 0.1;
+ }
+ } else {
+ scale = 1.0;
+ }
+
+ delta = ev->y - grab_y;
+ grab_y = ev->y;
+
+ fract = (delta / railrect.get_height());
+
+ fract = min (1.0, fract);
+ fract = max (-1.0, fract);
+
+ fract = -fract;
+
+ adj.set_value (adj.get_value() + scale * fract * (adj.get_upper() - adj.get_lower()));
+ }
+
+ return true;
+}
+
+void
+PixScroller::adjustment_changed ()
+{
+ int y = (int) rint ((overall_height - sliderrect.get_height()) * (adj.get_upper() - adj.get_value()));
+
+ if (y != sliderrect.get_y()) {
+ sliderrect.set_y(y);
+ queue_draw ();
+ }
+}
diff --git a/libs/gtkmm2ext/po/el_GR.po b/libs/gtkmm2ext/po/el_GR.po
new file mode 100644
index 0000000000..28dd199ea3
--- /dev/null
+++ b/libs/gtkmm2ext/po/el_GR.po
@@ -0,0 +1,79 @@
+# Σχολιαστικός Τίτλος.
+# Πνευματικά Δικαιώματα (C) YEAR Paul Davis
+# Το παρόν αρχείο διανέμεται υπό της ιδίας αδείας με του PACKAGE πακέτου.
+# ΠΡΩΤΟΣ ΔΗΜΙΟΥΡΓΟΣ <muadib@in.gr>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.99beta23\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-03-12 11:01-0500\n"
+"PO-Revision-Date: 2005-01-11\n"
+"Last-Translator: Muadibas\n"
+"Language-Team: Hellenic(Greek) <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: libs/gtkmm2ext/barcontroller.cc:416 libs/gtkmm2ext/bindable_button.cc:136
+#: libs/gtkmm2ext/controller.cc:50 libs/gtkmm2ext/slider_controller.cc:141
+msgid "operate MIDI controller now"
+msgstr "λειτουργία ελεγκτή MIDI τώρα"
+
+#: libs/gtkmm2ext/gtk_ui.cc:55
+msgid "cannot create thread request buffer key"
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:356 libs/gtkmm2ext/gtk_ui.cc:523
+msgid "programming error: "
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:688
+msgid "Press To Exit"
+msgstr ""
+
+#: libs/gtkmm2ext/mwc.cc:33 libs/gtkmm2ext/popup_selector.cc:34
+#: libs/gtkmm2ext/prompter.cc:32
+msgid "OK"
+msgstr "OK"
+
+#: libs/gtkmm2ext/newsavedialog.cc:26
+msgid "Location:"
+msgstr "Τοποθεσία:"
+
+#: libs/gtkmm2ext/newsavedialog.cc:27 libs/gtkmm2ext/newsavedialog.cc:265
+msgid "Browse ..."
+msgstr "Αναζήτηση ..."
+
+#: libs/gtkmm2ext/newsavedialog.cc:28 libs/gtkmm2ext/newsavedialog.cc:61
+#: libs/gtkmm2ext/prompter.cc:33
+msgid "Cancel"
+msgstr "Ακύρωση"
+
+#: libs/gtkmm2ext/newsavedialog.cc:30
+msgid "New folder"
+msgstr "Νέος φάκελος"
+
+#: libs/gtkmm2ext/newsavedialog.cc:31
+msgid "Add to favorites"
+msgstr "Πρόσθεση στα 'Αγαπημένα'"
+
+#: libs/gtkmm2ext/newsavedialog.cc:32
+msgid "Remove from favorites"
+msgstr "Απαλοιφή από τα 'Αγαπημένα'"
+
+#: libs/gtkmm2ext/newsavedialog.cc:33
+msgid "Show Hidden"
+msgstr "Ανάδειξη κρυμμένων"
+
+#: libs/gtkmm2ext/newsavedialog.cc:53 libs/gtkmm2ext/newsavedialog.cc:269
+msgid "Hide browser"
+msgstr "Απόκρυψη browser"
+
+#: libs/gtkmm2ext/popup_selector.cc:33 libs/gtkmm2ext/textviewer.cc:34
+msgid "Close"
+msgstr "Κλείσιμο"
+
+#: libs/gtkmm2ext/popup_selector.cc:35
+msgid "Rescan"
+msgstr "Ανανέωση"
diff --git a/libs/gtkmm2ext/po/es_ES.po b/libs/gtkmm2ext/po/es_ES.po
new file mode 100644
index 0000000000..fed58f060a
--- /dev/null
+++ b/libs/gtkmm2ext/po/es_ES.po
@@ -0,0 +1,78 @@
+# Copyright (C) 2004 Paul Davis
+# This file is distributed under the same license as the gtkmm2ext package.
+# Author: Alex Krohn <alexkrohn@fastmail.fm>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gtkmm2ext\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-03-12 11:01-0500\n"
+"PO-Revision-Date: 2004-02-13 00:35+0300\n"
+"Last-Translator: Alex Krohn alexkrohn@fastmail.fm\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: libs/gtkmm2ext/barcontroller.cc:416 libs/gtkmm2ext/bindable_button.cc:136
+#: libs/gtkmm2ext/controller.cc:50 libs/gtkmm2ext/slider_controller.cc:141
+msgid "operate MIDI controller now"
+msgstr "Operar controladora de MIDI ahora"
+
+#: libs/gtkmm2ext/gtk_ui.cc:55
+msgid "cannot create thread request buffer key"
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:356 libs/gtkmm2ext/gtk_ui.cc:523
+msgid "programming error: "
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:688
+msgid "Press To Exit"
+msgstr ""
+
+#: libs/gtkmm2ext/mwc.cc:33 libs/gtkmm2ext/popup_selector.cc:34
+#: libs/gtkmm2ext/prompter.cc:32
+msgid "OK"
+msgstr "ACEPTAR"
+
+#: libs/gtkmm2ext/newsavedialog.cc:26
+msgid "Location:"
+msgstr "Localizacin:"
+
+#: libs/gtkmm2ext/newsavedialog.cc:27 libs/gtkmm2ext/newsavedialog.cc:265
+msgid "Browse ..."
+msgstr "Seleccionar ..."
+
+#: libs/gtkmm2ext/newsavedialog.cc:28 libs/gtkmm2ext/newsavedialog.cc:61
+#: libs/gtkmm2ext/prompter.cc:33
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: libs/gtkmm2ext/newsavedialog.cc:30
+msgid "New folder"
+msgstr "Nueva carpeta"
+
+#: libs/gtkmm2ext/newsavedialog.cc:31
+msgid "Add to favorites"
+msgstr "Agregar a favoritos"
+
+#: libs/gtkmm2ext/newsavedialog.cc:32
+msgid "Remove from favorites"
+msgstr "Quitar de favoritos"
+
+#: libs/gtkmm2ext/newsavedialog.cc:33
+msgid "Show Hidden"
+msgstr "Mostrar ocultos"
+
+#: libs/gtkmm2ext/newsavedialog.cc:53 libs/gtkmm2ext/newsavedialog.cc:269
+msgid "Hide browser"
+msgstr "Ocultar explorador"
+
+#: libs/gtkmm2ext/popup_selector.cc:33 libs/gtkmm2ext/textviewer.cc:34
+msgid "Close"
+msgstr "Cerrar"
+
+#: libs/gtkmm2ext/popup_selector.cc:35
+msgid "Rescan"
+msgstr "Buscar de nuevo"
diff --git a/libs/gtkmm2ext/po/pt_BR.po b/libs/gtkmm2ext/po/pt_BR.po
new file mode 100644
index 0000000000..451e4adb3a
--- /dev/null
+++ b/libs/gtkmm2ext/po/pt_BR.po
@@ -0,0 +1,79 @@
+# Copyright (C) 2004 Paul Davis
+# This file is distributed under the same license as the gtkmm2ext package.
+# Authors: Alexander Franca <alexander@nautae.eti.br>
+# Chris Ross <chris.ross@tebibyte.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gtkmm2ext\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-03-12 11:01-0500\n"
+"PO-Revision-Date: 2004-05-17 20:36+0200\n"
+"Last-Translator: Chris Ross <chris.ross@tebibyte.org>\n"
+"Language-Team: Portuguese\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: libs/gtkmm2ext/barcontroller.cc:416 libs/gtkmm2ext/bindable_button.cc:136
+#: libs/gtkmm2ext/controller.cc:50 libs/gtkmm2ext/slider_controller.cc:141
+msgid "operate MIDI controller now"
+msgstr "Operar controladora de MIDI agora"
+
+#: libs/gtkmm2ext/gtk_ui.cc:55
+msgid "cannot create thread request buffer key"
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:356 libs/gtkmm2ext/gtk_ui.cc:523
+msgid "programming error: "
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:688
+msgid "Press To Exit"
+msgstr ""
+
+#: libs/gtkmm2ext/mwc.cc:33 libs/gtkmm2ext/popup_selector.cc:34
+#: libs/gtkmm2ext/prompter.cc:32
+msgid "OK"
+msgstr "OK"
+
+#: libs/gtkmm2ext/newsavedialog.cc:26
+msgid "Location:"
+msgstr "localizao:"
+
+#: libs/gtkmm2ext/newsavedialog.cc:27 libs/gtkmm2ext/newsavedialog.cc:265
+msgid "Browse ..."
+msgstr "Localizar ..."
+
+#: libs/gtkmm2ext/newsavedialog.cc:28 libs/gtkmm2ext/newsavedialog.cc:61
+#: libs/gtkmm2ext/prompter.cc:33
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: libs/gtkmm2ext/newsavedialog.cc:30
+msgid "New folder"
+msgstr "Novo diretrio"
+
+#: libs/gtkmm2ext/newsavedialog.cc:31
+msgid "Add to favorites"
+msgstr "Adicionar a favoritos"
+
+#: libs/gtkmm2ext/newsavedialog.cc:32
+msgid "Remove from favorites"
+msgstr "Remover de favoritos"
+
+#: libs/gtkmm2ext/newsavedialog.cc:33
+msgid "Show Hidden"
+msgstr "Mostrar ocultos"
+
+#: libs/gtkmm2ext/newsavedialog.cc:53 libs/gtkmm2ext/newsavedialog.cc:269
+msgid "Hide browser"
+msgstr "Ocultar explorador"
+
+#: libs/gtkmm2ext/popup_selector.cc:33 libs/gtkmm2ext/textviewer.cc:34
+msgid "Close"
+msgstr "Fechar"
+
+#: libs/gtkmm2ext/popup_selector.cc:35
+msgid "Rescan"
+msgstr "Buscar de novo"
diff --git a/libs/gtkmm2ext/po/ru_RU.po b/libs/gtkmm2ext/po/ru_RU.po
new file mode 100644
index 0000000000..4fc78f6987
--- /dev/null
+++ b/libs/gtkmm2ext/po/ru_RU.po
@@ -0,0 +1,78 @@
+# Copyright (C) 2004 Paul Davis
+# This file is distributed under the same license as the gtkmm2ext package.
+# Igor Blinov pitstop@nm.ru, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gtkmm2ext\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-03-12 11:01-0500\n"
+"PO-Revision-Date: 2004-02-13 00:35+0300\n"
+"Last-Translator: Igor Blinov pitstop@nm.ru\n"
+"Language-Team: Russian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=koi8-r\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: libs/gtkmm2ext/barcontroller.cc:416 libs/gtkmm2ext/bindable_button.cc:136
+#: libs/gtkmm2ext/controller.cc:50 libs/gtkmm2ext/slider_controller.cc:141
+msgid "operate MIDI controller now"
+msgstr " MIDI-"
+
+#: libs/gtkmm2ext/gtk_ui.cc:55
+msgid "cannot create thread request buffer key"
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:356 libs/gtkmm2ext/gtk_ui.cc:523
+msgid "programming error: "
+msgstr ""
+
+#: libs/gtkmm2ext/gtk_ui.cc:688
+msgid "Press To Exit"
+msgstr ""
+
+#: libs/gtkmm2ext/mwc.cc:33 libs/gtkmm2ext/popup_selector.cc:34
+#: libs/gtkmm2ext/prompter.cc:32
+msgid "OK"
+msgstr ""
+
+#: libs/gtkmm2ext/newsavedialog.cc:26
+msgid "Location:"
+msgstr ":"
+
+#: libs/gtkmm2ext/newsavedialog.cc:27 libs/gtkmm2ext/newsavedialog.cc:265
+msgid "Browse ..."
+msgstr " ..."
+
+#: libs/gtkmm2ext/newsavedialog.cc:28 libs/gtkmm2ext/newsavedialog.cc:61
+#: libs/gtkmm2ext/prompter.cc:33
+msgid "Cancel"
+msgstr ""
+
+#: libs/gtkmm2ext/newsavedialog.cc:30
+msgid "New folder"
+msgstr " "
+
+#: libs/gtkmm2ext/newsavedialog.cc:31
+msgid "Add to favorites"
+msgstr " "
+
+#: libs/gtkmm2ext/newsavedialog.cc:32
+msgid "Remove from favorites"
+msgstr " "
+
+#: libs/gtkmm2ext/newsavedialog.cc:33
+msgid "Show Hidden"
+msgstr " "
+
+#: libs/gtkmm2ext/newsavedialog.cc:53 libs/gtkmm2ext/newsavedialog.cc:269
+msgid "Hide browser"
+msgstr " "
+
+#: libs/gtkmm2ext/popup_selector.cc:33 libs/gtkmm2ext/textviewer.cc:34
+msgid "Close"
+msgstr ""
+
+#: libs/gtkmm2ext/popup_selector.cc:35
+msgid "Rescan"
+msgstr ""
diff --git a/libs/gtkmm2ext/popup.cc b/libs/gtkmm2ext/popup.cc
new file mode 100644
index 0000000000..540edba5c3
--- /dev/null
+++ b/libs/gtkmm2ext/popup.cc
@@ -0,0 +1,134 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+
+#include <gtkmm2ext/popup.h>
+#include <gtkmm2ext/utils.h>
+
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+
+PopUp::PopUp (Gtk::WindowPosition pos, unsigned int showfor_msecs, bool doh)
+ : Window (WINDOW_POPUP)
+{
+
+ realize ();
+ Glib::RefPtr<Gdk::Window> win (get_window());
+ win->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
+ add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+ signal_button_press_event().connect(mem_fun(*this,&PopUp::button_click));
+ set_border_width (12);
+ add (label);
+ set_position (pos);
+
+ delete_on_hide = doh;
+ popdown_time = showfor_msecs;
+ timeout = -1;
+}
+
+
+PopUp::~PopUp ()
+{
+}
+
+gint
+PopUp::remove_prompt_timeout (void *arg)
+{
+ PopUp *pup = (PopUp *) arg;
+
+ pup->remove ();
+ return FALSE;
+}
+
+static gint idle_delete (void *arg)
+{
+ delete static_cast<PopUp*> (arg);
+ return FALSE;
+}
+
+void
+PopUp::remove ()
+{
+ hide ();
+
+ if (delete_on_hide) {
+ std::cerr << "deleting prompter\n";
+ if (popdown_time != 0 && timeout != -1) {
+ gtk_timeout_remove (timeout);
+ }
+ gtk_idle_add (idle_delete, this);
+ }
+}
+
+void
+PopUp::touch ()
+{
+ if (is_visible ()) {
+ remove ();
+ } else {
+ set_usize_to_display_given_text (label, my_text.c_str(), 25, 10);
+ label.set_text (my_text);
+ show_all ();
+
+ if (popdown_time != 0) {
+ timeout = gtk_timeout_add (popdown_time,
+ remove_prompt_timeout,
+ this);
+ }
+ }
+}
+
+gint
+PopUp::button_click (GdkEventButton *ev)
+{
+ remove ();
+ return TRUE;
+}
+
+void
+PopUp::set_text (string txt)
+{
+ my_text = txt;
+}
+
+void
+PopUp::set_name (string name)
+{
+ Window::set_name (name);
+ label.set_name (name);
+}
+
+bool
+PopUp::on_delete_event (GdkEventAny* ev)
+{
+ hide();
+
+ if (delete_on_hide) {
+ std::cerr << "deleting prompter\n" << endl;
+ if (popdown_time != 0 && timeout != -1) {
+ gtk_timeout_remove (timeout);
+ }
+ gtk_idle_add (idle_delete, this);
+ }
+
+ return true;
+}
diff --git a/libs/gtkmm2ext/prompter.cc b/libs/gtkmm2ext/prompter.cc
new file mode 100644
index 0000000000..83a64e78d4
--- /dev/null
+++ b/libs/gtkmm2ext/prompter.cc
@@ -0,0 +1,118 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+
+#include <gtkmm2ext/prompter.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtkmm2ext;
+
+Prompter::Prompter (bool modal)
+ : Gtk::Window (Gtk::WINDOW_POPUP),
+ ok (_("OK")),
+ cancel (_("Cancel"))
+{
+ set_position (Gtk::WIN_POS_MOUSE);
+ set_name ("Prompter");
+ set_modal (modal);
+
+ add (packer);
+
+ entryLabel.set_line_wrap (true);
+ entryLabel.set_name ("PrompterLabel");
+
+ entryBox.set_homogeneous (false);
+ entryBox.set_spacing (25);
+ entryBox.set_border_width (10);
+ entryBox.pack_start (entryLabel);
+ entryBox.pack_start (entry, false, false);
+
+ buttonBox.set_homogeneous (true);
+ buttonBox.set_border_width (10);
+ buttonBox.pack_start (ok, false, true);
+ buttonBox.pack_start (cancel, false, true);
+
+ packer.pack_start (entryBox);
+ packer.pack_start (buttonBox);
+
+ entry.signal_activate().connect(mem_fun(*this,&Prompter::activated));
+ ok.signal_clicked().connect(mem_fun(*this,&Prompter::activated));
+ cancel.signal_clicked().connect(mem_fun(*this,&Prompter::cancel_click));
+ signal_delete_event().connect (mem_fun (*this, &Prompter::deleted));
+
+}
+
+void
+Prompter::change_labels (string okstr, string cancelstr)
+{
+ dynamic_cast<Gtk::Label*>(ok.get_child())->set_text (okstr);
+ dynamic_cast<Gtk::Label*>(cancel.get_child())->set_text (cancelstr);
+}
+
+void
+Prompter::on_realize ()
+{
+ Gtk::Window::on_realize ();
+ Glib::RefPtr<Gdk::Window> win (get_window());
+ win->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH|Gdk::DECOR_MENU));
+}
+
+void
+Prompter::on_map ()
+{
+ entry.grab_focus();
+ Gtk::Window::on_map ();
+}
+
+void
+Prompter::activated ()
+
+{
+ status = entered;
+ hide_all ();
+ done ();
+}
+
+void
+Prompter::cancel_click ()
+
+{
+ entry.set_text ("");
+ status = cancelled;
+ hide_all ();
+ done ();
+}
+
+bool
+Prompter::deleted (GdkEventAny *ev)
+{
+ cancel_click ();
+ return false;
+}
+
+void
+Prompter::get_result (string &str)
+
+{
+ str = entry.get_text ();
+}
diff --git a/libs/gtkmm2ext/selector.cc b/libs/gtkmm2ext/selector.cc
new file mode 100644
index 0000000000..371c946fe7
--- /dev/null
+++ b/libs/gtkmm2ext/selector.cc
@@ -0,0 +1,238 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+#include <string>
+
+#include <gtkmm2ext/selector.h>
+#include <gtkmm2ext/utils.h>
+#include <pbd/pathscanner.h>
+#include <pbd/error.h>
+
+using namespace std;
+using namespace Gtkmm2ext;
+
+Selector::Selector (void (*func)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg,
+ vector<string> titles)
+{
+ scroll.add (tview);
+ scroll.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+
+ pack_start (scroll, true, true);
+
+ vector<string>::iterator i;
+ for (i = titles.begin(); i != titles.end(); ++i) {
+ Gtk::TreeModelColumn<Glib::ustring> title;
+ column_records.add(title);
+ }
+
+ lstore = Gtk::ListStore::create(column_records);
+ tview.set_model(lstore);
+
+ update_contents.connect(mem_fun(*this,&Selector::rescan));
+
+ tview.show ();
+
+ refiller = func;
+ refill_arg = arg;
+ selected_row = -1;
+ selected_column = -1;
+}
+
+Selector::~Selector ()
+
+{
+ /* ensure that any row data set with set_row_data_full() is deleted */
+ hide_all ();
+ lstore.clear ();
+}
+
+void
+Selector::on_map()
+
+{
+ Gtk::VBox::on_map ();
+
+ selected_row = -1;
+ selected_column = -1;
+ refill();
+}
+
+void
+Selector::on_show()
+{
+ VBox::on_show();
+
+ rescan();
+}
+
+void
+Selector::reset (void (*func)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg)
+
+{
+ refiller = func;
+ refill_arg = arg;
+ selected_row = -1;
+ selected_column = -1;
+
+ refill();
+}
+
+void
+Selector::refill ()
+
+{
+ if (refiller) {
+ lstore.clear ();
+ refiller (lstore, refill_arg);
+ }
+}
+
+gint
+Selector::_accept (gpointer arg)
+
+{
+ ((Selector *) arg)->accept ();
+ return FALSE;
+}
+
+gint
+Selector::_chosen (gpointer arg)
+
+{
+ ((Selector *) arg)->chosen ();
+ return FALSE;
+}
+
+gint
+Selector::_shift_clicked (gpointer arg)
+{
+ ((Selector *) arg)->shift_clicked ();
+ return FALSE;
+}
+
+gint
+Selector::_control_clicked (gpointer arg)
+{
+ ((Selector *) arg)->control_clicked ();
+ return FALSE;
+}
+
+void
+Selector::accept ()
+{
+ Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
+ Gtk::TreeModel::iterator iter = tree_sel->get_selected();
+
+ if (iter) {
+ selection_made (tview, tree_sel);
+ } else {
+ cancel ();
+ }
+}
+
+void
+Selector::chosen ()
+
+{
+ Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
+ Gtk::TreeModel::iterator iter = tree_sel->get_selected();
+
+ if (iter) {
+ choice_made (tview, tree_sel);
+ } else {
+ cancel ();
+ }
+}
+
+void
+Selector::shift_clicked ()
+
+{
+ Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
+ Gtk::TreeModel::iterator iter = tree_sel->get_selected();
+
+ if (iter) {
+ shift_made (tview, tree_sel);
+ } else {
+ cancel ();
+ }
+}
+
+void
+Selector::control_clicked ()
+
+{
+ Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
+ Gtk::TreeModel::iterator iter = tree_sel->get_selected();
+
+ if (iter) {
+ control_made (tview, tree_sel);
+ } else {
+ cancel ();
+ }
+}
+
+void
+Selector::cancel ()
+
+{
+ Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
+ tree_sel->unselect_all();
+
+ selection_made (tview, tree_sel);
+}
+
+void
+Selector::rescan ()
+
+{
+ selected_row = -1;
+ selected_column = -1;
+ refill ();
+ show_all ();
+}
+
+struct string_cmp {
+ bool operator()(const string* a, const string* b) {
+ return *a < *b;
+ }
+};
+
+bool
+TreeView_Selector::on_button_press_event(GdkEventButton* ev)
+{
+ bool return_value = TreeView::on_button_press_event(ev);
+
+ if (ev && (ev->type == GDK_BUTTON_RELEASE || ev->type == GDK_2BUTTON_PRESS)) {
+ if (ev->state & Gdk::CONTROL_MASK) {
+ gtk_idle_add (Selector::_control_clicked, this);
+ } else if (ev->state & Gdk::SHIFT_MASK) {
+ gtk_idle_add (Selector::_shift_clicked, this);
+ } else if (ev->type == GDK_2BUTTON_PRESS) {
+ gtk_idle_add (Selector::_accept, this);
+ } else {
+ gtk_idle_add (Selector::_chosen, this);
+ }
+ }
+
+ return return_value;
+}
diff --git a/libs/gtkmm2ext/slider_controller.cc b/libs/gtkmm2ext/slider_controller.cc
new file mode 100644
index 0000000000..ca75fbb7b4
--- /dev/null
+++ b/libs/gtkmm2ext/slider_controller.cc
@@ -0,0 +1,183 @@
+/*
+ Copyright (C) 1998-99 Paul Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+#include <climits>
+
+#include <midi++/controllable.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/slider_controller.h>
+#include <gtkmm2ext/pix.h>
+
+#include "i18n.h"
+
+using namespace Gtkmm2ext;
+
+SliderController::SliderController (Pix *pixset,
+ Gtk::Adjustment *adj,
+ MIDI::Controllable *mc,
+ bool with_numeric)
+
+ : PixScroller (*adj, *pixset),
+ spin (*adj, 0, 2),
+ prompter (Gtk::WIN_POS_MOUSE, 30000, false),
+ midi_control (mc),
+ bind_button (2),
+ bind_statemask (Gdk::CONTROL_MASK)
+
+{
+ pixset->generate ();
+
+ signal_button_press_event().connect (mem_fun (this, &SliderController::button_press));
+ spin.set_name ("SliderControllerValue");
+ spin.set_size_request (70,-1); // should be based on font size somehow
+ spin.set_numeric (true);
+ spin.set_snap_to_ticks (false);
+
+ prompter.signal_unmap_event().connect (mem_fun (*this, &SliderController::prompter_hiding));
+
+ prompting = false;
+ unprompting = false;
+
+ if (mc) {
+ mc->learning_started.connect (mem_fun (*this, &SliderController::midicontrol_prompt));
+ mc->learning_stopped.connect (mem_fun (*this, &SliderController::midicontrol_unprompt));
+ }
+}
+
+void
+SliderController::set_value (float v)
+{
+ adj.set_value (v);
+}
+
+void
+SliderController::set_bind_button_state (guint button, guint statemask)
+{
+ bind_button = button;
+ bind_statemask = statemask;
+}
+
+void
+SliderController::get_bind_button_state (guint &button, guint &statemask)
+{
+ button = bind_button;
+ statemask = bind_statemask;
+}
+
+void
+SliderController::midi_learn()
+{
+ if (midi_control) {
+ prompting = true;
+ midi_control->learn_about_external_control ();
+ }
+}
+
+bool
+SliderController::button_press (GdkEventButton *ev)
+{
+ if ((ev->state & bind_statemask) && ev->button == bind_button) {
+ midi_learn ();
+ return true;
+ }
+
+ return false;
+}
+
+void
+SliderController::midicontrol_set_tip ()
+
+{
+ if (midi_control) {
+ // Gtkmm2ext::UI::instance()->set_tip (this, midi_control->control_description());
+ }
+}
+
+bool
+SliderController::prompter_hiding (GdkEventAny *ev)
+{
+ if (unprompting) {
+ if (midi_control) {
+ midi_control->stop_learning();
+ }
+ unprompting = false;
+ }
+
+ return false;
+}
+
+void
+SliderController::midicontrol_prompt ()
+
+{
+ if (prompting) {
+
+ string prompt = _("operate MIDI controller now");
+ prompter.set_text (prompt);
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+
+ unprompting = true;
+ prompting = false;
+ }
+}
+
+void
+SliderController::midicontrol_unprompt ()
+
+{
+ if (unprompting) {
+ Gtkmm2ext::UI::instance()->touch_display (&prompter);
+ unprompting = false;
+ }
+}
+
+
+VSliderController::VSliderController (Pix *pixset,
+ Gtk::Adjustment *adj,
+ MIDI::Controllable *mcontrol,
+ bool with_numeric)
+
+ : SliderController (pixset, adj, mcontrol, with_numeric)
+{
+ if (with_numeric) {
+ spin_frame.add (spin);
+ spin_frame.set_shadow_type (Gtk::SHADOW_IN);
+ spin_frame.set_name ("BaseFrame");
+ spin_hbox.pack_start (spin_frame, false, true);
+ // pack_start (spin_hbox, false, false);
+ }
+}
+
+HSliderController::HSliderController (Pix *pixset,
+ Gtk::Adjustment *adj,
+ MIDI::Controllable *mcontrol,
+ bool with_numeric)
+
+ : SliderController (pixset, adj, mcontrol, with_numeric)
+{
+ if (with_numeric) {
+ spin_frame.add (spin);
+ //spin_frame.set_shadow_type (Gtk::SHADOW_IN);
+ spin_frame.set_name ("BaseFrame");
+ spin_hbox.pack_start (spin_frame, false, true);
+ // pack_start (spin_hbox, false, false);
+ }
+}
diff --git a/libs/gtkmm2ext/tearoff.cc b/libs/gtkmm2ext/tearoff.cc
new file mode 100644
index 0000000000..c9dd89ac52
--- /dev/null
+++ b/libs/gtkmm2ext/tearoff.cc
@@ -0,0 +1,164 @@
+/*
+ Copyright (C) 2003 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <gtkmm2ext/tearoff.h>
+
+using namespace Gtkmm2ext;
+using namespace Gtk;
+using namespace std;
+
+TearOff::TearOff (Gtk::Widget& c)
+ : contents (c),
+ tearoff_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
+ close_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT)
+{
+ dragging = false;
+
+ tearoff_event_box.add (tearoff_arrow);
+ tearoff_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+ tearoff_event_box.signal_button_release_event().connect (mem_fun (*this, &TearOff::tearoff_click));
+
+ close_event_box.add (close_arrow);
+ close_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+ close_event_box.signal_button_release_event().connect (mem_fun (*this, &TearOff::close_click));
+
+ own_window = new Gtk::Window (Gtk::WINDOW_TOPLEVEL);
+ own_window->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::POINTER_MOTION_HINT_MASK);
+ own_window->set_resizable (false);
+// own_window->realize ();
+
+ Glib::RefPtr<Gdk::Window> win (own_window->get_window());
+ win->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
+
+ VBox* box1;
+ box1 = manage (new VBox);
+ box1->pack_start (close_event_box, false, false, 5);
+
+ window_box.pack_end (*box1, false, false, 2);
+ own_window->add (window_box);
+
+ own_window->signal_button_press_event().connect (mem_fun (*this, &TearOff::window_button_press));
+ own_window->signal_button_release_event().connect (mem_fun (*this, &TearOff::window_button_release));
+ own_window->signal_motion_notify_event().connect (mem_fun (*this, &TearOff::window_motion));
+ own_window->signal_delete_event().connect (mem_fun (*this, &TearOff::window_delete_event));
+
+ tearoff_arrow.set_name ("TearOffArrow");
+ close_arrow.set_name ("TearOffArrow");
+
+ VBox* box2;
+ box2 = manage (new VBox);
+ box2->pack_start (tearoff_event_box, false, false, 5);
+
+ pack_start (contents);
+ pack_start (*box2, false, false, 2);
+
+}
+
+TearOff::~TearOff ()
+{
+ delete own_window;
+}
+
+gint
+TearOff::tearoff_click (GdkEventButton* ev)
+{
+ remove (contents);
+ window_box.pack_start (contents);
+ own_window->set_name (get_name());
+ close_event_box.set_name (get_name());
+ own_window->show_all ();
+// own_window->realize ();
+ hide ();
+ Detach ();
+ return TRUE;
+}
+
+gint
+TearOff::close_click (GdkEventButton* ev)
+{
+ window_box.remove (contents);
+ pack_start (contents);
+ reorder_child (contents, 0);
+ own_window->hide ();
+ show_all ();
+ Attach ();
+ return TRUE;
+}
+
+gint
+TearOff::window_button_press (GdkEventButton* ev)
+{
+ dragging = true;
+ drag_x = ev->x_root;
+ drag_y = ev->y_root;
+
+ own_window->add_modal_grab();
+
+ return TRUE;
+}
+
+gint
+TearOff::window_button_release (GdkEventButton* ev)
+{
+ dragging = false;
+ own_window->remove_modal_grab();
+ return TRUE;
+}
+
+gint
+TearOff::window_delete_event (GdkEventAny* ev)
+{
+ return close_click(0);
+}
+
+gint
+TearOff::window_motion (GdkEventMotion* ev)
+{
+ gint x;
+ gint y;
+ gint mx, my;
+ double x_delta;
+ double y_delta;
+ Glib::RefPtr<Gdk::Window> win (own_window->get_window());
+
+ own_window->get_pointer (mx, my);
+
+ if (!dragging) {
+ return TRUE;
+ }
+
+ x_delta = ev->x_root - drag_x;
+ y_delta = ev->y_root - drag_y;
+
+ win->get_root_origin (x, y);
+ win->move ((gint) floor (x + x_delta), (gint) floor (y + y_delta));
+
+ drag_x = ev->x_root;
+ drag_y = ev->y_root;
+
+ return TRUE;
+}
+
+bool
+TearOff::torn_off() const
+{
+ return own_window->is_visible();
+}
diff --git a/libs/gtkmm2ext/textviewer.cc b/libs/gtkmm2ext/textviewer.cc
new file mode 100644
index 0000000000..8c89b845b7
--- /dev/null
+++ b/libs/gtkmm2ext/textviewer.cc
@@ -0,0 +1,127 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+#include <fstream>
+
+#include <gtkmm2ext/textviewer.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtkmm2ext;
+using namespace sigc;
+
+TextViewer::TextViewer (size_t xsize, size_t ysize) :
+ Gtk::Window (Gtk::WINDOW_TOPLEVEL),
+ Transmitter (Transmitter::Info), /* channel arg is irrelevant */
+ dismiss (_("Close"))
+{
+ set_size_request (xsize, ysize);
+
+ set_title ("Text Viewer");
+ set_name ("TextViewer");
+ set_resizable (true);
+ set_border_width (0);
+
+ vbox1.set_homogeneous (false);
+ vbox1.set_spacing (0);
+ add (vbox1);
+ vbox1.show ();
+
+ vbox2.set_homogeneous (false);
+ vbox2.set_spacing (10);
+ //vbox2.set_border_width (10);
+
+ vbox1.pack_start (vbox2, true, true, 0);
+ vbox2.show ();
+
+ vbox2.pack_start (scrollwin, TRUE, TRUE, 0);
+ scrollwin.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+ scrollwin.show ();
+
+ etext.set_editable (false);
+ etext.set_wrap_mode (Gtk::WRAP_WORD);
+ scrollwin.add (etext);
+ etext.show ();
+
+ vbox1.pack_start (dismiss, false, false, 0);
+ dismiss.show ();
+
+ dismiss.signal_clicked().connect(mem_fun (*this, &TextViewer::signal_released_handler));
+}
+
+void
+TextViewer::signal_released_handler()
+{
+ hide();
+}
+
+void
+TextViewer::insert_file (const string &path)
+
+{
+ char buf[1024];
+ ifstream f (path.c_str());
+
+ if (!f) {
+ return;
+ }
+
+ Glib::RefPtr<Gtk::TextBuffer> tb (etext.get_buffer());
+
+ tb->begin_user_action();
+ while (f) {
+ f.read (buf, sizeof (buf));
+
+ if (f.gcount()) {
+ buf[f.gcount()] = '\0';
+ string foo (buf);
+ tb->insert (tb->end(), foo);
+ }
+ }
+ tb->end_user_action();
+}
+
+void
+TextViewer::scroll_to_bottom ()
+
+{
+ Gtk::Adjustment *adj;
+
+ adj = scrollwin.get_vadjustment();
+ adj->set_value (MAX(0,(adj->get_upper() - adj->get_page_size())));
+}
+
+void
+TextViewer::deliver ()
+
+{
+ char buf[1024];
+ Glib::RefPtr<Gtk::TextBuffer> tb (etext.get_buffer());
+
+ while (!eof()) {
+ read (buf, sizeof (buf));
+ buf[gcount()] = '\0';
+ string foo (buf);
+ tb->insert (tb->end(), foo);
+ }
+ scroll_to_bottom ();
+ clear ();
+}
diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc
new file mode 100644
index 0000000000..0366c02f12
--- /dev/null
+++ b/libs/gtkmm2ext/utils.cc
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/gtkutils.h>
+
+#include "i18n.h"
+
+void
+Gtkmm2ext::set_usize_to_display_given_text (Gtk::Widget &w, const gchar *text,
+ gint hpadding, gint vpadding)
+
+{
+ w.ensure_style ();
+ set_usize_to_display_given_text(w, text, hpadding, vpadding);
+}
+
+gint
+do_not_propagate (GdkEventButton *ev)
+{
+ return TRUE;
+}
+
+void
+Gtkmm2ext::init ()
+{
+ // Necessary for gettext
+ (void) bindtextdomain(PACKAGE, LOCALEDIR);
+}
+