GUI enhancement: RGBV indicators below Histogram on behalf of Wolfgang K?hnel (see issue 683)

This commit is contained in:
michael
2011-07-26 21:34:55 -04:00
parent ed015d0184
commit 1a8c436c4b
13 changed files with 451 additions and 31 deletions

View File

@@ -317,6 +317,10 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) {
if (button==3) {
state = SNormal;
iarea->setToolHand ();
if (pmhlistener) {
pmhlistener->toggleFreeze();
}
}
iarea->redraw ();
updateCursor (x, y);
@@ -463,10 +467,13 @@ void CropWindow::pointerMoved (int x, int y) {
if (pmlistener) {
int mx, my;
translateCoord (x, y, mx, my);
if (!onArea (CropImage, x, y) || !cropHandler.cropPixbuf)
if (!onArea (CropImage, x, y) || !cropHandler.cropPixbuf) {
// pmlistener->pointerMoved (false, mx, my, -1, -1, -1);
pmlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1);
if (pmhlistener) {
pmhlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1);
}
}
else {
/*Glib::Mutex::Lock lock(cropHandler.cimg);
@@ -477,6 +484,7 @@ void CropWindow::pointerMoved (int x, int y) {
pmlistener->pointerMoved (true, mx, my, pix[0], pix[1], pix[2]);
*/
cropHandler.cimg.lock ();
int vx = x - xpos - imgX;
int vy = y - ypos - imgY;
@@ -486,9 +494,12 @@ void CropWindow::pointerMoved (int x, int y) {
int imwidth = cropHandler.cropPixbuf->get_width();
int imheight = cropHandler.cropPixbuf->get_height();
guint8* pix = cropHandler.cropPixbuftrue->get_pixels() + vy*cropHandler.cropPixbuf->get_rowstride() + vx*3;
if (vx < imwidth && vy < imheight)
if (vx < imwidth && vy < imheight) {
pmlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]);
if (pmhlistener) {
pmhlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]);
}
}
cropHandler.cimg.unlock ();
}

View File

@@ -78,6 +78,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener {
// crop gui listener
CropGUIListener* cropgl;
PointerMotionListener* pmlistener;
PointerMotionListener* pmhlistener;
std::list<CropWindowListener*> listeners;
CropWindow* observedCropWin;
@@ -134,7 +135,8 @@ class CropWindow : public LWButtonListener, public CropHandlerListener {
// listeners
void setCropGUIListener (CropGUIListener* cgl) { cropgl = cgl; }
void setPointerMotionListener (PointerMotionListener* pml) { pmlistener = pml; }
void setPointerMotionListener (PointerMotionListener* pml) { pmlistener = pml; }
void setPointerMotionHListener (PointerMotionListener* pml) { pmhlistener = pml; }
// crop window listeners
void addCropWindowListener (CropWindowListener* l) { listeners.push_back (l); }

View File

@@ -51,7 +51,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
if (options.histogramPosition>0) {
histogramPanel = Gtk::manage (new HistogramPanel ());
histogramPanel->set_size_request (-1, 150);
histogramPanel->set_size_request (-1, 160);
if (options.histogramPosition==1) leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4);
} else histogramPanel = NULL;
@@ -270,7 +270,8 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
tpc->addPParamsChangeListener (this);
iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener());
iarea->imageArea->setPointerMotionListener (navigator);
iarea->imageArea->setImageAreaToolListener (tpc);
iarea->imageArea->setPointerMotionHListener (histogramPanel);
iarea->imageArea->setImageAreaToolListener (tpc);
// initialize components
info->set_active (options.showInfo);

View File

@@ -21,69 +21,376 @@
#include <string.h>
#include <LUT.h>
//
//
// HistogramPanel
HistogramPanel::HistogramPanel () {
// Gtk::HBox* outer_hbox = Gtk::manage (new Gtk::HBox (false, 0));
histogramArea = Gtk::manage (new HistogramArea ());
histogramRGBArea = Gtk::manage (new HistogramRGBArea ());
Gtk::VBox* left_vbox = Gtk::manage (new Gtk::VBox (false, 0));
left_vbox->pack_start (*histogramArea, Gtk::PACK_EXPAND_WIDGET, 2);
left_vbox->pack_start (*histogramRGBArea, Gtk::PACK_SHRINK, 2);
set_size_request (-1, 170);
histogramArea->set_size_request (-1, 150);
histogramRGBArea->set_size_request(-1, 10);
showRed = Gtk::manage (new Gtk::ToggleButton (M("HISTOGRAM_BUTTON_R")));
showGreen = Gtk::manage (new Gtk::ToggleButton (M("HISTOGRAM_BUTTON_G")));
showBlue = Gtk::manage (new Gtk::ToggleButton (M("HISTOGRAM_BUTTON_B")));
showValue = Gtk::manage (new Gtk::ToggleButton (M("HISTOGRAM_BUTTON_L")));
showRAW = Gtk::manage (new Gtk::ToggleButton (M("HISTOGRAM_BUTTON_RAW")));
Gtk::VBox* vbox = Gtk::manage (new Gtk::VBox (false, 0));
showRed->set_active (true);
showGreen->set_active (true);
showBlue->set_active (true);
showValue->set_active (true);
showRAW->set_active (false);
vbox->pack_start (*showRed, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showGreen, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showBlue, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showValue, Gtk::PACK_SHRINK, 2);
vbox->pack_end (*showRAW, Gtk::PACK_SHRINK, 2);
pack_start (*histogramArea);
pack_end (*vbox, Gtk::PACK_SHRINK, 2);
showBAR = Gtk::manage (new Gtk::ToggleButton (M("HISTOGRAM_BUTTON_BAR")));
showRed->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
showGreen->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
showBlue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
showValue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
showRAW->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
show_all ();
showBAR->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
showRed->set_tooltip_text (M("HISTOGRAM_TOOLTIP_R"));
showGreen->set_tooltip_text (M("HISTOGRAM_TOOLTIP_G"));
showBlue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_B"));
showValue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_L"));
showRAW->set_tooltip_text (M("HISTOGRAM_TOOLTIP_RAW"));
showBAR->set_tooltip_text (M("HISTOGRAM_TOOLTIP_BAR"));
rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) );
Gtk::VBox* vbox = Gtk::manage (new Gtk::VBox (false, 0));
showRed->set_active (true);
showGreen->set_active (true);
showBlue->set_active (true);
showValue->set_active (true);
showRAW->set_active (false);
showBAR->set_active (true);
vbox->pack_start (*showRed, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showGreen, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showBlue, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showValue, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showRAW, Gtk::PACK_SHRINK, 2);
vbox->pack_start (*showBAR, Gtk::PACK_SHRINK, 2);
pack_start (*left_vbox,Gtk::PACK_EXPAND_WIDGET, 2);
pack_start (*vbox, Gtk::PACK_SHRINK, 2);
show_all ();
rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) );
}
void HistogramPanel::resized (Gtk::Allocation& req) {
rconn.block (true);
if (req.get_width()/2>150)
set_size_request (req.get_width(), 150);
else
if (req.get_width()/2>150) {
set_size_request (req.get_width(), 170);
histogramArea->set_size_request (req.get_width(), 150);
histogramRGBArea->set_size_request (req.get_width(), 10);
// Probably set R,G,B,V, RAW, and BAR button here to their original size if resizing below is implemented.
}
else {
set_size_request (req.get_width(), req.get_width()/2);
histogramArea->set_size_request (req.get_width(), req.get_width()/2);
histogramRGBArea->set_size_request(req.get_width(),5);
// Probably reduce R,G,B,V, RAW, and BAR button here a to a half-sized version.
}
rconn.block (false);
histogramArea->renderHistogram ();
histogramArea->queue_draw ();
if (histogramRGBArea->getFreeze()==true) {
histogramRGBArea->updateFreeze(false);
// set histogramRGBArea invalid;
histogramRGBArea->renderRGBMarks(-1, -1, -1);
// re-set freeze to old state
histogramRGBArea->updateFreeze(true);
histogramRGBArea->queue_draw ();
}
else {
// set histogramRGBArea invalid;
histogramRGBArea->renderRGBMarks(-1, -1, -1);
histogramRGBArea->queue_draw ();
}
}
void HistogramPanel::rgbv_toggled () {
// Update Display
histogramArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active());
histogramArea->queue_draw ();
histogramRGBArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showBAR->get_active());
histogramRGBArea->renderRGBMarks (0,0,0);
histogramArea->queue_draw ();
}
void HistogramPanel::setHistRGBInvalid () {
// do something to un-show vertical bars
histogramRGBArea->renderRGBMarks(-1, -1, -1);
histogramRGBArea->queue_draw ();
}
// "Freeze" is not a button, but a RMB-click, so this is not in the RGBV-Toggle method
void HistogramPanel::toggleFreeze () {
if (histogramRGBArea->getFreeze()==true) { histogramRGBArea->updateFreeze(false); }
else {
if (histogramRGBArea->getShow()==true) {
histogramRGBArea->updateFreeze(true);
}
}
return;
}
void HistogramPanel::pointerMoved (bool validPos, Glib::ustring profile, int x, int y, int r, int g, int b) {
if (!validPos) {
// do something to un-show vertical bars
histogramRGBArea->renderRGBMarks(-1, -1, -1);
histogramRGBArea->queue_draw ();
}
else {
// do something to show vertical bars
histogramRGBArea->renderRGBMarks(r, g, b);
histogramRGBArea->queue_draw ();
}
}
//
//
//
// HistogramRGBArea
HistogramRGBArea::HistogramRGBArea () :
frozen(false), valid(false), showMode(true), rawMode(false), needLuma(true), needRed(true), needGreen(true), needBlue(true) {
harih = new HistogramRGBAreaIdleHelper;
harih->harea = this;
harih->destroyed = false;
harih->pending = 0;
signal_style_changed().connect( sigc::mem_fun(*this, &HistogramRGBArea::styleChanged) );
}
HistogramRGBArea::~HistogramRGBArea () {
if (harih->pending)
harih->destroyed = true;
else
delete harih;
}
bool HistogramRGBArea::getFreeze() {
return(frozen);
}
bool HistogramRGBArea::getShow() {
return(showMode);
}
void HistogramRGBArea::updateFreeze (bool f) {
frozen = f;
return;
}
void HistogramRGBArea::renderRGBMarks (int r, int g, int b) {
if (!is_realized ())
return;
if (frozen) {
return;
}
Glib::RefPtr<Gdk::Window> window = get_window();
int winx, winy, winw, winh, wind;
window->get_geometry(winx, winy, winw, winh, wind);
overlay = Gdk::Pixmap::create (window, winw, winh, -1);
Glib::RefPtr<Gdk::GC> ovrl = Gdk::GC::create(overlay);
Glib::RefPtr<Gtk::Style> style = get_style ();
if (!showMode) {
ovrl->set_foreground (style->get_bg (Gtk::STATE_NORMAL));
overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh);
if (rgbgc_ && overlay) {
window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); }
return; }
else {
ovrl->set_foreground (style->get_fg (Gtk::STATE_NORMAL));
overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh);
if (rgbgc_ && overlay) {
window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); }
}
Cairo::RefPtr<Cairo::Context> cr = overlay->create_cairo_context();
cr->set_line_width (1.0);
if ( r != -1 && g != -1 && b != -1 ) {
if (needRed) {
// Red
cr->set_source_rgb(1.0, 0.0, 0.0);
cr->move_to((int)(r*(winw/256.0)), 0);
cr->line_to((int)(r*(winw/256.0)), winh-0);
cr->stroke();
}
if (needGreen) {
// Green
cr->set_source_rgb(0.0, 1.0, 0.0);
cr->move_to((int)(g*(winw/256.0)), 0);
cr->line_to((int)(g*(winw/256.0)), winh-0);
cr->stroke();
}
if (needBlue) {
// Blue
cr->set_source_rgb(0.0, 0.0, 1.0);
cr->move_to((int)(b*(winw/256.0)), 0);
cr->line_to((int)(b*(winw/256.0)), winh-0);
cr->stroke();
}
if (needLuma) {
// Luma
cr->set_source_rgb(1.0, 1.0, 1.0);
cr->move_to((int)((r+g+b)/3*(winw/256.0)), 0);
cr->line_to((int)((r+g+b)/3*(winw/256.0)), winh-0);
cr->stroke();
}
}
}
int histrgbupdate (void* data) {
gdk_threads_enter ();
HistogramRGBAreaIdleHelper* harih = (HistogramRGBAreaIdleHelper*)data;
if (harih->destroyed) {
if (harih->pending == 1)
delete harih;
else
harih->pending--;
gdk_threads_leave ();
return 0;
}
harih->harea->renderRGBMarks(-1,-1,-1);
harih->harea->queue_draw ();
harih->pending--;
gdk_threads_leave ();
return 0;
}
void HistogramRGBArea::update (int valh, int rh, int gh, int bh) {
if (valh) {
val=valh;
r=rh;
g=gh;
b=bh;
valid = true;
}
else
valid = false;
harih->pending++;
g_idle_add (histrgbupdate, harih);
}
void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool show) {
needRed = r;
needGreen = g;
needBlue = b;
needLuma = l;
rawMode = raw;
showMode = show;
// Histogram RGB BAR button logic goes here
// Disable bar button when RAW histogram is displayed
if ( rawMode && showMode) {
showMode = false;
}
// When un-showing the bar, set the freeze state to off
if (!showMode) {
updateFreeze(false);
}
}
void HistogramRGBArea::on_realize () {
Gtk::DrawingArea::on_realize();
Glib::RefPtr<Gdk::Window> window = get_window();
rgbgc_ = Gdk::GC::create(window);
add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK);
Glib::RefPtr<Gdk::Colormap> rgbcolormap = get_default_colormap();
black = Gdk::Color ("black");
red = Gdk::Color ("red");
green = Gdk::Color ("green");
blue = Gdk::Color ("blue");
lgray = Gdk::Color ("gray75");
mgray = Gdk::Color ("gray50");
dgray = Gdk::Color ("gray25");
rgbcolormap->alloc_color(black);
rgbcolormap->alloc_color(white);
rgbcolormap->alloc_color(red);
rgbcolormap->alloc_color(green);
rgbcolormap->alloc_color(blue);
rgbcolormap->alloc_color(lgray);
rgbcolormap->alloc_color(mgray);
rgbcolormap->alloc_color(dgray);
}
bool HistogramRGBArea::on_expose_event(GdkEventExpose* event) {
Glib::RefPtr<Gdk::Window> window = get_window();
// on_realize & RenderRGBMarks have to be called before
if (rgbgc_ && overlay) {
window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1);
}
return true;
}
bool HistogramRGBArea::on_button_press_event (GdkEventButton* event) {
if (event->type==GDK_2BUTTON_PRESS && event->button==1) {
// do something. Maybe un-freeze ?
}
return true;
}
void HistogramRGBArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
white = get_style()->get_base(Gtk::STATE_NORMAL);
queue_draw ();
}
//
//
//
// HistogramArea
HistogramArea::HistogramArea () :
valid(false), showFull(true), oldwidth(-1), needLuma(true), needRed(true), needGreen(true), needBlue(true), rawMode(false) {
lhist(256);
rhist(256);
ghist(256);
bhist(256);
haih = new HistogramAreaIdleHelper;
haih->harea = this;
haih->destroyed = false;
@@ -350,4 +657,3 @@ bool HistogramArea::on_button_press_event (GdkEventButton* event) {
}
return true;
}

View File

@@ -19,10 +19,13 @@
#ifndef _HISTOGRAMPANEL_
#define _HISTOGRAMPANEL_
#include <gtkmm.h>
#include <glibmm.h>
#include <LUT.h>
#include <pointermotionlistener.h>
class HistogramArea;
struct HistogramAreaIdleHelper {
HistogramArea* harea;
@@ -30,6 +33,68 @@ struct HistogramAreaIdleHelper {
int pending;
};
class HistogramRGBArea;
struct HistogramRGBAreaIdleHelper {
HistogramRGBArea* harea;
bool destroyed;
int pending;
};
class HistogramRGBArea : public Gtk::DrawingArea {
protected:
Glib::RefPtr<Gdk::GC> rgbgc_;
Glib::RefPtr<Gdk::Pixmap> overlay;
Gdk::Color black;
Gdk::Color white;
Gdk::Color red;
Gdk::Color green;
Gdk::Color blue;
Gdk::Color lgray;
Gdk::Color mgray;
Gdk::Color dgray;
int val;
int r;
int g;
int b;
bool frozen;
bool valid;
bool needRed;
bool needGreen;
bool needBlue;
bool needLuma;
bool rawMode;
bool showMode;
HistogramRGBAreaIdleHelper* harih;
public:
HistogramRGBArea();
~HistogramRGBArea();
void renderRGBMarks (int r, int g, int b);
void updateFreeze (bool f);
bool getFreeze ();
bool getShow ();
void update (int val, int rh, int gh, int bh);
void updateOptions (bool r, bool g, bool b, bool l, bool raw, bool show);
void on_realize();
bool on_expose_event(GdkEventExpose* event);
bool on_button_press_event (GdkEventButton* event);
void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
private:
// Some ...
};
class HistogramArea : public Gtk::DrawingArea {
protected:
@@ -75,18 +140,21 @@ class HistogramArea : public Gtk::DrawingArea {
LUTu & data, double scale, int hsize, int & ui, int & oi);
};
class HistogramPanel : public Gtk::HBox {
class HistogramPanel : public Gtk::HBox, public PointerMotionListener {
protected:
HistogramArea* histogramArea;
HistogramRGBArea* histogramRGBArea;
Gtk::ToggleButton* showRed;
Gtk::ToggleButton* showGreen;
Gtk::ToggleButton* showBlue;
Gtk::ToggleButton* showValue;
Gtk::ToggleButton* showRAW;
Gtk::ToggleButton* showBAR;
sigc::connection rconn;
void setHistInvalid ();
public:
@@ -95,6 +163,13 @@ class HistogramPanel : public Gtk::HBox {
void histogramChanged (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu &histLuma, LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw) {
histogramArea->update (histRed, histGreen, histBlue, histLuma, histRedRaw, histGreenRaw, histBlueRaw);
}
// pointermotionlistener interface
void pointerMoved (bool validPos, Glib::ustring profile, int x, int y, int r, int g, int b);
// added pointermotionlistener interface
void toggleFreeze();
// TODO should be protected
void setHistRGBInvalid ();
void rgbv_toggled ();
void resized (Gtk::Allocation& req);
};

View File

@@ -30,6 +30,7 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) {
infotext = "";
cropgl = NULL;
pmlistener = NULL;
pmhlistener = NULL;
focusGrabber = NULL;
mainCropWindow = NULL;
previewHandler = NULL;
@@ -78,6 +79,7 @@ void ImageArea::on_resized (Gtk::Allocation& req) {
mainCropWindow->addCropWindowListener (this);
mainCropWindow->setCropGUIListener (cropgl);
mainCropWindow->setPointerMotionListener (pmlistener);
mainCropWindow->setPointerMotionHListener (pmhlistener);
mainCropWindow->setPosition (0, 0);
mainCropWindow->setSize (get_width(), get_height(), false); // this execute the refresh itself
}
@@ -259,6 +261,7 @@ void ImageArea::addCropWindow () {
cw->zoom11();
cw->setCropGUIListener (cropgl);
cw->setPointerMotionListener (pmlistener);
cw->setPointerMotionHListener (pmhlistener);
cropWins.push_front (cw);
// Position the new crop window in a checkerboard, or used the last position
@@ -422,6 +425,15 @@ void ImageArea::setPointerMotionListener (PointerMotionListener* pml) {
mainCropWindow->setPointerMotionListener (pml);
}
void ImageArea::setPointerMotionHListener (PointerMotionListener* pml) {
pmhlistener = pml;
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
(*i)->setPointerMotionHListener (pml);
if (mainCropWindow)
mainCropWindow->setPointerMotionHListener (pml);
}
ToolMode ImageArea::getToolMode () {
if (listener)

View File

@@ -55,6 +55,7 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener {
CropWindow* focusGrabber;
CropGUIListener* cropgl;
PointerMotionListener* pmlistener;
PointerMotionListener* pmhlistener;
ImageAreaToolListener* listener;
CropWindow* getCropWindow (int x, int y);
@@ -89,7 +90,8 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener {
void updateScrollbars ();
void setCropGUIListener (CropGUIListener* l);
void setPointerMotionListener (PointerMotionListener* pml);
void setPointerMotionListener (PointerMotionListener* pml);
void setPointerMotionHListener (PointerMotionListener* pml);
void setImageAreaToolListener (ImageAreaToolListener* l) { listener = l; }
void setPreviewHandler (PreviewHandler* ph);
PreviewHandler* getPreviewHandler () { return previewHandler; }

View File

@@ -24,6 +24,7 @@ class PointerMotionListener {
public:
// virtual void pointerMoved (bool validPos, int x, int y, int r, int g, int b) {}
virtual void pointerMoved (bool validPos, Glib::ustring profile, int x, int y, int r, int g, int b) {}
virtual void toggleFreeze () {}
};
#endif