diff --git a/livesupport/modules/widgets/etc/Makefile.in b/livesupport/modules/widgets/etc/Makefile.in index 0414d2997..fdfadbf5f 100644 --- a/livesupport/modules/widgets/etc/Makefile.in +++ b/livesupport/modules/widgets/etc/Makefile.in @@ -21,7 +21,7 @@ # # # Author : $Author: maroy $ -# Version : $Revision: 1.1 $ +# Version : $Revision: 1.2 $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/widgets/etc/Makefile.in,v $ # # @configure_input@ @@ -106,7 +106,8 @@ LDFLAGS = @LDFLAGS@ -pthread \ #------------------------------------------------------------------------------- # Dependencies #------------------------------------------------------------------------------- -WIDGETS_LIB_OBJS = ${TMP_DIR}/ImageButton.o +WIDGETS_LIB_OBJS = ${TMP_DIR}/ImageButton.o \ + ${TMP_DIR}/Button.o TEST_EXE_OBJS = ${TMP_DIR}/TestWindow.o \ ${TMP_DIR}/main.o diff --git a/livesupport/modules/widgets/include/LiveSupport/Widgets/Button.h b/livesupport/modules/widgets/include/LiveSupport/Widgets/Button.h new file mode 100644 index 000000000..6e810377d --- /dev/null +++ b/livesupport/modules/widgets/include/LiveSupport/Widgets/Button.h @@ -0,0 +1,290 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport 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. + + LiveSupport 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 LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: maroy $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/widgets/include/LiveSupport/Widgets/Button.h,v $ + +------------------------------------------------------------------------------*/ +#ifndef LiveSupport_Widgets_Button_h +#define LiveSupport_Widgets_Button_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#include +#include + +#include "LiveSupport/Core/Ptr.h" + + +namespace LiveSupport { +namespace Widgets { + +using namespace LiveSupport::Core; + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A button holding a text. + * + * @author $Author: maroy $ + * @version $Revision: 1.1 $ + */ +class Button : public Gtk::Button +{ + private: + /** + * The possible states of the button. + */ + typedef enum { passiveState, rollState, selectedState } State; + + /** + * The Gdk::Window object, used to draw inside this button. + */ + Glib::RefPtr gdkWindow; + + /** + * The Graphics Context, used to draw. + */ + Glib::RefPtr gc; + + /** + * The text displayed inside the button. + */ + Ptr::Ref label; + + /** + * The state of the button. + */ + State state; + + /** + * The left image for the passive state of the button. + */ + Glib::RefPtr passiveImageLeft; + + /** + * The center image for the passive state of the button. + */ + Glib::RefPtr passiveImageCenter; + + /** + * The right image for the passive state of the button. + */ + Glib::RefPtr passiveImageRight; + + /** + * The left image of the button, when the mouse hovers above it. + */ + Glib::RefPtr rollImageLeft; + + /** + * The center image of the button, when the mouse hovers above it. + */ + Glib::RefPtr rollImageCenter; + + /** + * The right image of the button, when the mouse hovers above it. + */ + Glib::RefPtr rollImageRight; + + /** + * Default constructor. + */ + Button(void) throw () + { + } + + + protected: + /** + * Handle the size request event. + * + * @param requisition the size request, also being the ouptut + * parameter. + */ + virtual void + on_size_request(Gtk::Requisition* requisition) + throw (); + + /** + * Handle the size allocate event. + * + * @param allocation the allocated size. + */ + virtual void + on_size_allocate(Gtk::Allocation& allocation) + throw (); + + /** + * Handle the map event. + */ + virtual void + on_map() throw (); + + /** + * Handle the unmap event. + */ + virtual void + on_unmap() throw (); + + /** + * Handle the realize event. + */ + virtual void + on_realize() throw (); + + /** + * Handle the unrealize event. + */ + virtual void + on_unrealize() throw (); + + /** + * Handle the expose event. + * + * @param event the actual expose event recieved. + * @return true if something was drawn (?) + */ + virtual bool + on_expose_event(GdkEventExpose* event) throw (); + + /** + * Execute a function on all children of this container. + * + * @param includeInternals true if the callback function should + * also be called on the internals, false otherwise. + * @param callback the callback function to execute on the children. + * @param callbackData the data passed to the callback function. + */ + virtual void + forall_vfunc(gboolean includeInternals, + GtkCallback callback, + gpointer callbackData) + throw (); + + /** + * Handle the add event. + * + * @param child the child being added to the widget. + */ + virtual void + on_add(Gtk::Widget* child) throw (); + + /** + * Handle the remove event. + * + * @param child the child to remove from the widget. + */ + virtual void + on_remove(Gtk::Widget* child) throw (); + + /** + * Tell what kind of children this container accepts. + * + * @return the type of children this container accepts. + */ + virtual GtkType + child_type_vfunc() const throw (); + + /** + * Handle the event when the mouse enters the button area. + */ + virtual void + on_enter(void) throw (); + + /** + * Handle the event when the mouse leaves the button area. + */ + virtual void + on_leave(void) throw (); + + + public: + /** + * Constructor, with only one state. + * + * @param label the text to display in the button + * @param leftImage the left image for the button + * @param centerImage the center image for the button + * @param rightImage the right image for the button + */ + Button(const Glib::ustring & label, + Glib::RefPtr leftImage, + Glib::RefPtr centerImage, + Glib::RefPtr rightImage) throw (); + + /** + * Constructor, with a rollover state. + * Passive and rollover images are expected to be of the same size. + * + * @param label the text to display in the button + * @param passiveImageLeft the left image for the button, passive + * @param passiveImageCenter the center image for the button, passive + * @param passiveImageRight the right image for the button, passive + * @param rollImageLeft the left image for the button, onmouseover + * @param rollImageCenter the center image for the button, onmouseover + * @param rollImageRight the right image for the button, onmouseover + */ + Button(const Glib::ustring & label, + Glib::RefPtr passiveImageLeft, + Glib::RefPtr passiveImageCenter, + Glib::RefPtr passiveImageRight, + Glib::RefPtr rollImageLeft, + Glib::RefPtr rollImageCenter, + Glib::RefPtr rollImageRight) throw (); + + /** + * A virtual destructor. + */ + virtual + ~Button(void) throw (); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Widgets +} // namespace LiveSupport + +#endif // LiveSupport_Widgets_Button_h + diff --git a/livesupport/modules/widgets/src/Button.cxx b/livesupport/modules/widgets/src/Button.cxx new file mode 100644 index 000000000..7c46b1ae1 --- /dev/null +++ b/livesupport/modules/widgets/src/Button.cxx @@ -0,0 +1,387 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport 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. + + LiveSupport 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 LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: maroy $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/widgets/src/Button.cxx,v $ + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#include "LiveSupport/Widgets/Button.h" + + +using namespace LiveSupport::Core; +using namespace LiveSupport::Widgets; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Constructor. + *----------------------------------------------------------------------------*/ +Button :: Button(const Glib::ustring & label, + Glib::RefPtr leftImage, + Glib::RefPtr centerImage, + Glib::RefPtr rightImage) + throw () +{ + set_flags(Gtk::NO_WINDOW); + + state = passiveState; + this->passiveImageLeft = leftImage; + this->passiveImageCenter = centerImage; + this->passiveImageRight = rightImage; + this->rollImageLeft.clear(); + this->rollImageCenter.clear(); + this->rollImageRight.clear(); + + this->label.reset(new Gtk::Label(label)); + this->label->set_parent(*this); +} + + +/*------------------------------------------------------------------------------ + * Constructor. + *----------------------------------------------------------------------------*/ +Button :: Button(const Glib::ustring & label, + Glib::RefPtr passiveImageLeft, + Glib::RefPtr passiveImageCenter, + Glib::RefPtr passiveImageRight, + Glib::RefPtr rollImageLeft, + Glib::RefPtr rollImageCenter, + Glib::RefPtr rollImageRight) + throw () +{ + set_flags(Gtk::NO_WINDOW); + + state = passiveState; + this->passiveImageLeft = passiveImageLeft; + this->passiveImageCenter = passiveImageCenter; + this->passiveImageRight = passiveImageRight; + this->rollImageLeft = rollImageLeft; + this->rollImageCenter = rollImageCenter; + this->rollImageRight = rollImageRight; + + this->label.reset(new Gtk::Label(label)); + this->label->set_parent(*this); +} + + +/*------------------------------------------------------------------------------ + * Destructor. + *----------------------------------------------------------------------------*/ +Button :: ~Button(void) throw () +{ +} + + +/*------------------------------------------------------------------------------ + * Handle the size request event. + *----------------------------------------------------------------------------*/ +void +Button :: on_size_request(Gtk::Requisition* requisition) throw () +{ + *requisition = Gtk::Requisition(); + + Gtk::Requisition labelRequisition = label->size_request();; + + requisition->width = passiveImageLeft->get_width() + + labelRequisition.width + + passiveImageRight->get_width(); + requisition->height = passiveImageCenter->get_height(); +} + + +/*------------------------------------------------------------------------------ + * Handle the size allocate event. + * We will not be given heights or widths less than we have requested, + * though we might get more. + *----------------------------------------------------------------------------*/ +void +Button :: on_size_allocate(Gtk::Allocation& allocation) throw () +{ + set_allocation(allocation); + + if (gdkWindow) { + gdkWindow->move_resize( allocation.get_x(), + allocation.get_y(), + allocation.get_width(), + allocation.get_height() ); + } + + Gtk::Allocation labelAlloc; + + labelAlloc.set_x(passiveImageLeft->get_width()); + labelAlloc.set_y((allocation.get_height() + - passiveImageCenter->get_height()) + / 2); + labelAlloc.set_width(allocation.get_width() + - passiveImageLeft->get_width() + - passiveImageRight->get_width()); + labelAlloc.set_height(passiveImageCenter->get_height()); + + label->size_allocate(labelAlloc); +} + + +/*------------------------------------------------------------------------------ + * Execute a function on all the children. + * As this widget has no children, don't do anything. + *----------------------------------------------------------------------------*/ +void +Button :: forall_vfunc(gboolean includeInternals, + GtkCallback callback, + gpointer callbackData) throw () +{ + callback((GtkWidget*) label->gobj(), callbackData); +} + + +/*------------------------------------------------------------------------------ + * Handle the add child widget event. + * As this widget has no children, don't do anything. + *----------------------------------------------------------------------------*/ +void +Button :: on_add(Gtk::Widget* child) throw () +{ +} + + +/*------------------------------------------------------------------------------ + * Handle the remove child widget event. + * As this widget has no children, don't do anything. + *----------------------------------------------------------------------------*/ +void +Button :: on_remove(Gtk::Widget* child) throw () +{ +} + + +/*------------------------------------------------------------------------------ + * Return what kind of widgets can be added to this container. + * As this widget has no children, return G_TYPE_NONE always. + *----------------------------------------------------------------------------*/ +GtkType +Button :: child_type_vfunc() const throw () +{ + return G_TYPE_NONE; +} + + +/*------------------------------------------------------------------------------ + * Handle the map event. + *----------------------------------------------------------------------------*/ +void +Button :: on_map() throw () +{ + Gtk::Button::on_map(); +} + + +/*------------------------------------------------------------------------------ + * Handle the unmap event. + *----------------------------------------------------------------------------*/ +void +Button :: on_unmap() throw () +{ + Gtk::Button::on_unmap(); +} + + +/*------------------------------------------------------------------------------ + * Handle the realize event. + *----------------------------------------------------------------------------*/ +void +Button :: on_realize() throw () +{ + Gtk::Button::on_realize(); + + if (!gdkWindow) { + // create the Gdk::Window, if it didn't exist before + + GdkWindowAttr attributes; + memset(&attributes, 0, sizeof(attributes)); + + Gtk::Allocation allocation = get_allocation(); + + // set initial position and size of the Gdk::Window + attributes.x = allocation.get_x(); + attributes.y = allocation.get_y(); + attributes.width = allocation.get_width(); + attributes.height = allocation.get_height(); + + attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + + + gdkWindow = Gdk::Window::create(get_window(), + &attributes, + GDK_WA_X | GDK_WA_Y); + unset_flags(Gtk::NO_WINDOW); + set_window(gdkWindow); + + // make the widget receive expose events + gdkWindow->set_user_data(gobj()); + + // allocate a GC for use in on_expose_event() + gc = Gdk::GC::create(gdkWindow); + } +} + + +/*------------------------------------------------------------------------------ + * Handle the unrealize event. + *----------------------------------------------------------------------------*/ +void +Button :: on_unrealize() throw () +{ + gdkWindow.clear(); + gc.clear(); + + Gtk::Button::on_unrealize(); +} + + +/*------------------------------------------------------------------------------ + * Handle the expose event. + *----------------------------------------------------------------------------*/ +bool +Button :: on_expose_event(GdkEventExpose* event) throw () +{ + if (event->count > 0) { + return false; + } + + if (gdkWindow) { + gdkWindow->clear(); + + Glib::RefPtr leftImage; + Glib::RefPtr centerImage; + Glib::RefPtr rightImage; + + switch (state) { + case passiveState: + default: + leftImage = passiveImageLeft; + centerImage = passiveImageCenter; + rightImage = passiveImageRight; + break; + + case rollState: + leftImage = rollImageLeft ? rollImageLeft : passiveImageLeft; + centerImage = rollImageCenter ? rollImageCenter + : passiveImageCenter; + rightImage = rollImageRight ? rollImageRight + : passiveImageRight; + break; + } + + // draw everything vertically centered, but horizontally stretched + // out + int x = 0; + int y = (get_height() - centerImage->get_height()) / 2; + int maxX = get_width() - rightImage->get_width(); + + // draw the left image + leftImage->render_to_drawable(gdkWindow, + get_style()->get_black_gc(), + 0, 0, + x, + y, + leftImage->get_width(), + leftImage->get_height(), + Gdk::RGB_DITHER_NONE, + 0, 0); + + // draw as many center images, as necessary + for (x = leftImage->get_width(); + x < maxX; + x += centerImage->get_width()) { + + centerImage->render_to_drawable(gdkWindow, + get_style()->get_black_gc(), + 0, 0, + x, + y, + centerImage->get_width(), + centerImage->get_height(), + Gdk::RGB_DITHER_NONE, + 0, 0); + } + + // draw the right image + rightImage->render_to_drawable(gdkWindow, + get_style()->get_black_gc(), + 0, 0, + maxX, + y, + rightImage->get_width(), + rightImage->get_height(), + Gdk::RGB_DITHER_NONE, + 0, 0); + } + + Gtk::Container::on_expose_event(event); + + return false; +} + + +/*------------------------------------------------------------------------------ + * Handle the mouse enter event. + *----------------------------------------------------------------------------*/ +void +Button :: on_enter(void) throw () +{ + state = rollState; + + Gtk::Button::on_enter(); +} + + +/*------------------------------------------------------------------------------ + * Handle the mouse leave event. + *----------------------------------------------------------------------------*/ +void +Button :: on_leave(void) throw () +{ + state = passiveState; + + Gtk::Button::on_leave(); +} + diff --git a/livesupport/modules/widgets/src/TestWindow.cxx b/livesupport/modules/widgets/src/TestWindow.cxx index bbf0c17af..2a617eed3 100644 --- a/livesupport/modules/widgets/src/TestWindow.cxx +++ b/livesupport/modules/widgets/src/TestWindow.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/widgets/src/TestWindow.cxx,v $ ------------------------------------------------------------------------------*/ @@ -55,6 +55,7 @@ using namespace LiveSupport::Widgets; TestWindow :: TestWindow (void) throw () { + // init the imageButton Glib::RefPtr passiveImage; Glib::RefPtr rollImage; @@ -63,8 +64,35 @@ TestWindow :: TestWindow (void) imageButton.reset(new ImageButton(passiveImage, rollImage)); + // init the button + Glib::RefPtr passiveImageLeft; + Glib::RefPtr passiveImageCenter; + Glib::RefPtr passiveImageRight; + Glib::RefPtr rollImageLeft; + Glib::RefPtr rollImageCenter; + Glib::RefPtr rollImageRight; + + passiveImageLeft = Gdk::Pixbuf::create_from_file("var/button_left.png"); + passiveImageCenter = Gdk::Pixbuf::create_from_file("var/button_centre.png"); + passiveImageRight = Gdk::Pixbuf::create_from_file("var/button_right.png"); + rollImageLeft = Gdk::Pixbuf::create_from_file("var/button_left_roll.png"); + rollImageCenter = Gdk::Pixbuf::create_from_file( + "var/button_centre_roll.png"); + rollImageRight = Gdk::Pixbuf::create_from_file( + "var/button_right_roll.png"); + + button.reset(new Button("Hello, World!", + passiveImageLeft, + passiveImageCenter, + passiveImageRight, + rollImageLeft, + rollImageCenter, + rollImageRight)); + + // create and set up the layout layout.reset(new Gtk::Table()); layout->attach(*imageButton, 0, 1, 0, 1); + layout->attach(*button, 0, 1, 1, 2); add(*layout); show_all(); diff --git a/livesupport/modules/widgets/src/TestWindow.h b/livesupport/modules/widgets/src/TestWindow.h index 54bbb4da5..ffc30047b 100644 --- a/livesupport/modules/widgets/src/TestWindow.h +++ b/livesupport/modules/widgets/src/TestWindow.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/widgets/src/TestWindow.h,v $ ------------------------------------------------------------------------------*/ @@ -45,6 +45,7 @@ #include "LiveSupport/Core/Ptr.h" +#include "LiveSupport/Widgets/Button.h" #include "LiveSupport/Widgets/ImageButton.h" @@ -65,7 +66,7 @@ using namespace LiveSupport::Core; * A window, enabling interactive testing of UI components. * * @author $Author: maroy $ - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ class TestWindow : public Gtk::Window { @@ -80,6 +81,11 @@ class TestWindow : public Gtk::Window */ Ptr::Ref imageButton; + /** + * A button. + */ + Ptr