Codebase list imview / eba15666-00c2-4d63-af5d-caf07788990a/main imviewWindow.cxx
eba15666-00c2-4d63-af5d-caf07788990a/main

Tree @eba15666-00c2-4d63-af5d-caf07788990a/main (Download .tar.gz)

imviewWindow.cxx @eba15666-00c2-4d63-af5d-caf07788990a/mainraw · history · blame

/*------------------------------------------------------------------------
 *
 * A subclass of the Fl_Window, that has a few nicer features
 * More specifically, can impose size limit on the window.
 *
 * Hugues Talbot	 5 Jan 2001
 *      
 *-----------------------------------------------------------------------*/

#include "imview.hxx"
#include "imviewWindow.hxx"
#include "imageIO.hxx"
#include "imageViewer.hxx"
#include "menubar.hxx"
#include  <assert.h>

extern imageViewer   *mainViewer;
extern imViewMenuBar *mainMenuBar;

imviewWindow::imviewWindow(int w, int h, const char *label)
#ifdef IMVIEW_USES_DBLBUF
    : Fl_Overlay_Window(w,h,label)
#else
        : Fl_Window(w, h, label)
#endif
{
    w_lower_limit = w_upper_limit =  h_lower_limit = h_upper_limit = -1;
    zoomSelRect.w = zoomSelRect.h = -1;
#ifdef HAVE_XINERAMA
    screens = 0;
    xinerama_screen = -1;
#endif 
    return;
}

imviewWindow::imviewWindow(int x, int y, int w, int h, const char *label)
#ifdef IMVIEW_USES_DBLBUF
    : Fl_Overlay_Window(x,y,w,h,label)
#else
        : Fl_Window(x,y,w,h,label)
#endif
{
    w_lower_limit = w_upper_limit =  h_lower_limit = h_upper_limit = -1;
    zoomSelRect.w = zoomSelRect.h = -1;
    return;
}

imviewWindow::~imviewWindow()
{
    return;
}

void imviewWindow::removeMainMenu(void)
{
    int hh = h() - MENUHEIGHT; 

    dbgprintf("imviewWindow: removing main menu\n");
    // removing all from group:

    remove(mainMenuBar);
    remove(mainViewer);

    h_lower_limit -= MENUHEIGHT;
    size(w(), h()-MENUHEIGHT); // resize main window to smaller size

    mainMenuBar->resize(0,0,w(),0);
    mainViewer->resize(0,0,w(),hh); // smaller size here

    add(mainViewer);
    add(mainMenuBar);

    dbgprintf("imviewWindow: done\n");
    return;
}

void imviewWindow::addMainMenu(void)
{
    int hh = h() + MENUHEIGHT;

    dbgprintf("imviewWindow: adding main menu\n");

    // need to do that to avoid spurious resizes by the toolkit
    remove(mainMenuBar);
    remove(mainViewer);

    h_upper_limit += MENUHEIGHT;
    size(w(), hh); // resizes main window to accomodate menu

    mainViewer->resize(0,MENUHEIGHT, w(), hh);
    mainMenuBar->resize(0,0,w(), MENUHEIGHT);
    
    add(mainViewer);
    add(mainMenuBar);
    
    dbgprintf("imviewWindow: done\n");
    return;
}

// resize with limits.
// I don't understand why FLTK's limit dont work.
void imviewWindow::resize(int x,int y, int w, int h)
{
    bool change = false;
    
    assert(mainViewer);
    displaymode m = mainViewer->getdisplaymode() ;


    if (m == IMV_DISPLAY_WINDOW_FIT_IMG) {
        dbgprintf("Main window asked to resize to: %dx%d+%d+%d\n",
                  w,h,x,y);

        // looking for weird resizes coming from the WM
        if ((w == SWIDTH) && (h == SHEIGHT)
            && (w != w_upper_limit) && (h != h_upper_limit)) {
            dbgprintf("Weird resize coming from the windows manager. Resize denied!\n");
            return; // HA!
        }

        if ((w_upper_limit > 0) && (w > w_upper_limit)) {
            w = w_upper_limit;
            change = true;
        }

        if ((h_upper_limit > 0) && (h > h_upper_limit)) {
            h = h_upper_limit;
            change = true;
        }

        if ((w_lower_limit > 0) && (w < w_lower_limit)) {
            w = w_lower_limit;
            change = true;
        }

        if ((h_lower_limit > 0) && (h < h_lower_limit)) {
            h = h_lower_limit;
            change = true;
        }

        if (change)
            dbgprintf("In fact resizing to: %dx%d+%d+%d\n",
                      w,h,x,y);
        else
            dbgprintf("Resize accepted\n");
    } else if (m == IMV_DISPLAY_IMG_FIT_WINDOW) {
        dbgprintf("Stretch to fit mode\n");
    } else if (m == IMV_DISPLAY_DECOUPLE_WIN_IMG) {
	dbgprintf("Decoupled display mode\n");
    }

#ifdef IMVIEW_USES_DBL
    Fl_Overlay_Window::resize(x,y,w,h);
#else
    Fl_Window::resize(x,y,w,h);
#endif

    return;
}


void imviewWindow::size_range(int minw,
			      int minh,
			      int maxw,
			      int maxh,
			      int dw,
			      int dh,
			      int aspect)
{
    w_lower_limit = minw;
    w_upper_limit = maxw;
    h_lower_limit = minh;
    h_upper_limit = maxh;

    dbgprintf("Limits set to [%dx%d--%dx%d]\n",
	     minw, minh,
              maxw, maxh);
#ifdef IMVIEW_USES_DBL
    Fl_Overlay_Window::size_range(minw, minh, maxw, maxh, dw, dh, aspect);
#else
    Fl_Window::size_range(minw, minh, maxw, maxh, dw, dh, aspect);
#endif
    return;
}

// This is the way an overlay needs to be drawn now.
// We allow for rectangle selections, lines, etc.
void imviewWindow::draw_overlay(void)
{
    dbgprintf("Draw_overlay called\n");
    if (zoomSelRect.w > 0 && zoomSelRect.h > 0 ) {
        dbgprintf("Drawing rectangular overlay: (%d,%d),(%d x %d)\n",
                  zoomSelRect.x,
                  zoomSelRect.y,
                  zoomSelRect.w,
                  zoomSelRect.h);
        fl_color(FL_RED);
        fl_rect(zoomSelRect.x,
                zoomSelRect.y,
                zoomSelRect.w,
                zoomSelRect.h);
    }

    return;
}

int  imviewWindow::currentDisplayWidth(void)
{
    int w = Fl::w();

#ifdef HAVE_XINERAMA
    // expensive call, how to speed that up?
    if (XineramaIsActive(fl_display)) {
	getXineramaInfo();
	w = screens[xinerama_screen].width;
    }
#endif

    return w;
}

int  imviewWindow::currentDisplayHeight(void)
{
    int h = Fl::h();

#ifdef HAVE_XINERAMA
    // expensive call, how to speed that up?
    if (XineramaIsActive(fl_display)) {
	getXineramaInfo();
	h = screens[xinerama_screen].height;
    }
#endif

    return h;
}

#ifdef HAVE_XINERAMA

// put the relevant information in the screens array
// and find which screen the mouse is on.
void imviewWindow::getXineramaInfo(void)
{
    int num_screens;
    int currentX, currentY;
    Fl::get_mouse(currentX, currentY);
    // get the screens configuration
    if (!screens)
	screens = XineramaQueryScreens(fl_display, &num_screens);
    for (int i = 0 ; i < num_screens ; ++i) {
	// find out which screen we are on
	if ((screens[i].x_org <= currentX)
	    && (screens[i].y_org <= currentY)
	    && ((screens[i].x_org+screens[i].width) >= currentX)
	    && ((screens[i].y_org+screens[i].height) >= currentY)) {
	    dbgprintf("xinerama screen is: %d\n", i);
	    xinerama_screen = i;
	    break;
	}
    }
    if (xinerama_screen < 0) {
	dbgprintf("Could not find suitable screen for some reason, defaulting to 0\n");
	xinerama_screen = 0;
    }

    return;
}


// totally replaces the stock fltk methods.
void imviewWindow::fullscreen()
{
    if (XineramaIsActive(fl_display)) {
	getXineramaInfo();
	border(0); // Fl_Window public method
	// resize window to the dimensions of the screen
	if (x() == screens[xinerama_screen].x_org) x(screens[xinerama_screen].x_org + 1); // force a call to XResizeWindow (?)
	resize(screens[xinerama_screen].x_org,
	       screens[xinerama_screen].y_org,
	       screens[xinerama_screen].width,
	       screens[xinerama_screen].height);
	// done
    } else {
	// just call the stock member function, it will be fine.
	Fl_Window::fullscreen();
    }
    return;
}

#endif // HAVE_XINERAMA