rawTherapee/rtgui/editwindow.cc
Hombre 8b2eac9a3d Pipette and "On Preview Widgets" branch. See issue 227
The pipette part is already working quite nice but need to be finished. The widgets part needs more work...
2014-01-21 23:37:36 +01:00

226 lines
7.3 KiB
C++

/*
* This file is part of RawTherapee.
*
* RawTherapee 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 3 of the License, or
* (at your option) any later version.
*
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#include "editwindow.h"
#include "options.h"
#include "preferences.h"
#include "cursormanager.h"
#include "rtwindow.h"
#include <gtk/gtk.h>
#include "rtimage.h"
#include "threadutils.h"
static EditWindow* editWnd = NULL;
// Check if the system has more than one display and option is set
bool EditWindow::isMultiDisplayEnabled() {
return options.multiDisplayMode>0 && Gdk::Screen::get_default()->get_n_monitors ()>1;
}
// Should only be created once, auto-creates window on correct display
EditWindow* EditWindow::getInstance(RTWindow* p)
{
if ( editWnd == NULL )
{
static MyMutex smutex_;
MyMutex::MyLock lock(smutex_);
if ( editWnd == 0 )
{
editWnd = new EditWindow(p);
// Determine the other display and maximize the window on that
const Glib::RefPtr< Gdk::Window >& wnd=p->get_window();
int monNo=p->get_screen()->get_monitor_at_window (wnd);
Gdk::Rectangle lMonitorRect;
editWnd->get_screen()->get_monitor_geometry(monNo==0 ? 1:0, lMonitorRect);
editWnd->move(lMonitorRect.get_x(), lMonitorRect.get_y());
editWnd->maximize();
editWnd->show();
} else {
editWnd->show_all();
}
}
return editWnd;
}
EditWindow::EditWindow (RTWindow* p) : parent(p) , isFullscreen(false) {
Glib::ustring fName = "rt-logo.png";
Glib::ustring fullPath = RTImage::findIconAbsolutePath(fName);
#ifdef GLIBMM_EXCEPTIONS_ENABLED
try { set_default_icon_from_file (fullPath);
} catch(Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); }
#else
{ std::auto_ptr<Glib::Error> error;
set_default_icon_from_file (fullPath, error);
}
#endif //GLIBMM_EXCEPTIONS_ENABLED
set_title("RawTherapee "+ M("EDITWINDOW_TITLE"));
property_allow_shrink() = true;
set_modal(false);
set_resizable(true);
property_destroy_with_parent().set_value(false);
signal_window_state_event().connect( sigc::mem_fun(*this, &EditWindow::on_window_state_event) );
mainNB = Gtk::manage (new Gtk::Notebook ());
mainNB->set_scrollable (true);
mainNB->signal_switch_page().connect_notify( sigc::mem_fun(*this, &EditWindow::on_mainNB_switch_page) );
signal_key_press_event().connect( sigc::mem_fun(*this, &EditWindow::keyPressed) );
Gtk::VBox* mainBox = Gtk::manage (new Gtk::VBox ());
mainBox->pack_start (*mainNB);
add (*mainBox);
show_all ();
}
void EditWindow::on_realize () {
Gtk::Window::on_realize ();
cursorManager.init (get_window());
}
bool EditWindow::on_window_state_event(GdkEventWindowState* event) {
if (!event->new_window_state) {
// Window mode
options.windowMaximized = false;
}
else if (event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) {
// Fullscreen mode
options.windowMaximized = true;
}
return true;
}
void EditWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) {
if (page_num > 1) {
EditorPanel *ep = static_cast<EditorPanel*>(mainNB->get_nth_page(page_num));
ep->setAspect();
}
}
void EditWindow::addEditorPanel (EditorPanel* ep, const std::string &name) {
ep->setParent (parent);
// construct closeable tab for the image
Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ());
hb->pack_start (*Gtk::manage (new RTImage ("rtwindow.png")));
hb->pack_start (*Gtk::manage (new Gtk::Label (name)));
Gtk::Button* closeb = Gtk::manage (new Gtk::Button ());
closeb->set_image (*Gtk::manage(new RTImage ("gtk-close.png")));
closeb->set_relief (Gtk::RELIEF_NONE);
closeb->set_focus_on_click (false);
// make the button as small as possible
Glib::RefPtr<Gtk::RcStyle> style = Gtk::RcStyle::create ();
style->set_xthickness (0);
style->set_ythickness (0);
closeb->modify_style (style);
closeb->signal_clicked().connect( sigc::bind (sigc::mem_fun(*this, &EditWindow::remEditorPanel) , ep));
hb->pack_end (*closeb);
hb->set_spacing (2);
hb->show_all ();
mainNB->append_page (*ep, *hb);
mainNB->set_current_page (mainNB->page_num (*ep));
mainNB->set_tab_reorderable (*ep, true);
epanels[ name ] = ep;
filesEdited.insert ( name );
parent->fpanel->refreshEditedState (filesEdited);
ep->setAspect();
}
void EditWindow::remEditorPanel (EditorPanel* ep) {
epanels.erase (ep->getShortName());
filesEdited.erase (ep->getShortName ());
parent->fpanel->refreshEditedState (filesEdited);
mainNB->remove_page (*ep);
// TODO: save options if wanted
}
bool EditWindow::selectEditorPanel(const std::string &name) {
std::map<Glib::ustring, EditorPanel*>::iterator iep = epanels.find(name);
if (iep!=epanels.end()) {
mainNB->set_current_page (mainNB->page_num (*iep->second));
return true;
}
return false;
}
bool EditWindow::keyPressed (GdkEventKey* event) {
bool ctrl = event->state & GDK_CONTROL_MASK;
if(event->keyval == GDK_F11) {
toggleFullscreen();
return true;
}
else {
if(mainNB->get_n_pages ()>0) { //pass the handling for the editor panels, if there are any
if (event->keyval == GDK_w && ctrl){ //remove editor panel
EditorPanel* ep = static_cast<EditorPanel*>(mainNB->get_nth_page (mainNB->get_current_page()));
remEditorPanel (ep);
return true;
}
else if(mainNB->get_n_pages ()>0){
EditorPanel* ep = static_cast<EditorPanel*>(mainNB->get_nth_page (mainNB->get_current_page()));
return ep->handleShortcutKey (event);
}
}
return false;
}
}
void EditWindow::toggleFullscreen () {
isFullscreen ? unfullscreen() : fullscreen();
isFullscreen = !isFullscreen;
}
bool EditWindow::on_delete_event(GdkEventAny* event) {
// Check if any editor is still processing, and do NOT quit if so. Otherwise crashes and inconsistent caches
bool isProcessing=false;
for ( std::set <Glib::ustring>::iterator iter = filesEdited.begin(); iter != filesEdited.end() && !isProcessing; iter++ ) {
if (epanels[*iter]->getIsProcessing()) isProcessing=true;
}
if (isProcessing) return false;
for ( std::set <Glib::ustring>::iterator iter = filesEdited.begin(); iter != filesEdited.end(); iter++ )
mainNB->remove_page (*epanels[*iter]);
epanels.clear();
filesEdited.clear();
parent->fpanel->refreshEditedState (filesEdited);
hide ();
return true;
}