/*------------------------------------------------------------------------
*
* 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