Logo Search packages:      
Sourcecode: agave version File versions  Download package

gcs-colorswatch.cc

/*******************************************************************************
 *  PROJECT: GNOME Colorscheme
 *
 *  AUTHOR: Jonathon Jongsma
 *
 *  Copyright (c) 2005 Jonathon Jongsma
 *
 *  License:
 *    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
 *
 *******************************************************************************/

#include <list> // for list of drag targets
#include <limits>   // for numeric_limits<>::max()
#include <gdkmm/gc.h>
#include <pangomm/layout.h>
#include <glibmm/ustring.h>

#include "gcs-colorswatch.h"
#include "core/log-stream.h"
#include "gcs-i18n.h"


namespace gcs
{
    static const unsigned int RED_BYTE_POS = 3;
    static const unsigned int GREEN_BYTE_POS = 2;
    static const unsigned int BLUE_BYTE_POS = 1;

    namespace Widgets
    {
        ColorPtr ColorSwatch::m_white = gcs::Color::create("#FFFFFF");
        ColorPtr ColorSwatch::m_black = gcs::Color::create("#000000");
        Gtk::Tooltips* ColorSwatch::pTooltips = NULL;
        int ColorSwatch::tooltip_refs = 0;

00050         ColorSwatch::ColorSwatch(ColorPtr bg) :
            m_background(bg), m_minSize(12),
            m_borderWidth(1),
            m_swatchPadding(6)
        {
            // if this is the first ColorSwatch, create a tooltip object and
            // increment the reference value.  The Tooltip object will be
            // deleted when the reference count reaches 0`
            if (!tooltip_refs++)
            {
                pTooltips = new Gtk::Tooltips();
            }
            // get_window() would return 0 because the Gdk::Window has not yet been
            // realized So we can only allocate the colors here - the rest will
            // happen in on_realize().
            m_colormap = get_default_colormap();
            m_colormap->alloc_color(m_black->gdk());
            m_colormap->alloc_color(m_white->gdk());
            alloc_bg();

            // Targets for drag and drop:
            std::list<Gtk::TargetEntry> listTargets;
            listTargets.push_back(Gtk::TargetEntry("application/x-color"));
            listTargets.push_back(Gtk::TargetEntry("UTF8_STRING"));
            listTargets.push_back(Gtk::TargetEntry("text/plain"));

            // set the swatch as a drag source
            drag_source_set(listTargets);
            signal_drag_data_get().connect(sigc::mem_fun(*this, &ColorSwatch::on_drag_data_get));
            signal_drag_begin().connect(sigc::mem_fun(*this, &ColorSwatch::set_color_icon));

        }


00084         ColorSwatch::ColorSwatch(const ColorSwatch& c) :
            m_background(c.m_background)
        {
            m_borderGC = c.m_borderGC;
            m_colormap = c.m_colormap;
        }


        ColorSwatch::~ColorSwatch(void)
        {
            // clear the tooltip that is associated with this swatch
            pTooltips->unset_tip(*this);
            // delete the tooltips object if there are no more colorswatch
            // objects that are using it
            if (!(--tooltip_refs))
            {
                delete pTooltips;
            }
        }


00105         void ColorSwatch::on_realize(void)
        {
            // We need to call the base on_realize()
            Gtk::DrawingArea::on_realize();

            // Now we can allocate any additional resources we need
            Glib::RefPtr<Gdk::Window> window = get_window();
            // set the size of the swatch.
            set_size_request(m_minSize, m_minSize);
            m_borderGC = Gdk::GC::create(window);
            m_borderGC->set_line_attributes(m_borderWidth, Gdk::LINE_SOLID,
                    Gdk::CAP_BUTT, Gdk::JOIN_MITER);
            m_borderGC->set_foreground(m_black->gdk());
            add_events(Gdk::BUTTON_PRESS_MASK | Gdk::ENTER_NOTIFY_MASK |
                    Gdk::LEAVE_NOTIFY_MASK);
            pTooltips->set_tip(*this, m_background->get_hexstring());
        }


        bool ColorSwatch::on_expose_event(GdkEventExpose *e)
        {
            redraw();
            return true;
        }


00131         void ColorSwatch::redraw(void)
        {
            Glib::RefPtr<Gdk::Window> win = get_window();
            win->set_background(m_background->gdk());
            win->clear();
            int winWidth, winHeight;
            win->get_size(winWidth, winHeight);
            /* First draw an outline around the edge (in black, i guess) */
            if (m_borderWidth > 0)
            {
                win->draw_rectangle(m_borderGC, false, m_borderWidth/2, m_borderWidth/2,
                        winWidth - m_borderWidth, winHeight - m_borderWidth);
            }
        }


00147         void ColorSwatch::alloc_bg(void)
        {
            m_colormap->alloc_color(m_background->gdk());
        }


00153         void ColorSwatch::set_color(ColorPtr bg)
        {
            m_background = bg;
            alloc_bg();
            //LOG("background_ = " << m_background);
            redraw();
            // Currently tooltips are only used for the palette, and we never
            // change the color of those swatches, so this isn't really needed
            // at this point.
            //pTooltips->set_tip(*this, m_background->get_hexstring());
        }


        void ColorSwatch::set_border_width(gint width)
        {
            m_borderWidth = width;
        }


00172         bool ColorSwatch::on_button_press_event(GdkEventButton *e)
        {
            //Then do our custom stuff:
            if (e->type == GDK_BUTTON_PRESS)
            {
                // User pressed left mouse button
                if (e->button == 1)
                {
                    // let listeners know that we've been selected
                    m_signal_selected.emit();
                }
            }
            return false;
        }


        void ColorSwatch::on_drag_data_get(const
                Glib::RefPtr<Gdk::DragContext>& context,
                Gtk::SelectionData& selection_data, guint info,
                guint time)
        {
            if (selection_data.get_target() == "application/x-color")
            {
                /* type: application/x-color
                 * format::16
                 * data[0]: red
                 * data[1]: green
                 * data[2]: blue
                 * data[3]: opacity
                 */
                guint16 color[4];
                color[0] = m_background->gdk().get_red();
                color[1] = m_background->gdk().get_green();
                color[2] = m_background->gdk().get_blue();
                color[3] = std::numeric_limits<guint16>::max();
                selection_data.set(selection_data.get_target(), 16,
                        reinterpret_cast<const guchar*>(&color), sizeof(color));
            }
            else if (selection_data.targets_include_text())
            {
                selection_data.set_text(m_background->get_hexstring());
            }
        }


        void ColorSwatch::set_color_icon(const Glib::RefPtr<Gdk::DragContext>& context)
        {
            using std::numeric_limits;

            const int bits_per_sample = 8;
            const int w = 32;
            const int h = 32;
            Glib::RefPtr<Gdk::Pixbuf> pixbuf =
                Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, bits_per_sample,
                        w, h);
            Gdk::Color c = m_background->gdk();
            guint32 pixel = 0;

            // populate the 'pixel' value from the red, green, and blue color
            // values
            *(reinterpret_cast<guchar*>(&pixel) + RED_BYTE_POS) =
                (guchar) (((double) c.get_red() / (double)
                           numeric_limits<gushort>::max()) *
                          numeric_limits<guchar>::max());

            *(reinterpret_cast<guchar*>(&pixel) + GREEN_BYTE_POS) =
                (guchar) (((double) c.get_green() / (double)
                           numeric_limits<gushort>::max()) *
                          numeric_limits<guchar>::max());

            *(reinterpret_cast<guchar*>(&pixel) + BLUE_BYTE_POS) =
                (guchar) (((double) c.get_blue() / (double)
                           numeric_limits<gushort>::max()) *
                          numeric_limits<guchar>::max());

            pixbuf->fill(pixel);
            drag_source_set_icon(pixbuf);
        }

    } // namespace Widgets
} // namespace gcs

Generated by  Doxygen 1.6.0   Back to index