/*
 * $Id: keyboard.cxx,v 4.6 2003/11/07 06:40:23 hut66au Exp $
 *
 * Imview, the portable image analysis application
 * http://www.cmis.csiro.au/Hugues.Talbot/imview
 * ----------------------------------------------------------
 *
 *  Imview is an attempt to provide an image display application
 *  suitable for professional image analysis. It was started in
 *  1997 and is mostly the result of the efforts of Hugues Talbot,
 *  Image Analysis Project, CSIRO Mathematical and Information
 *  Sciences, with help from others (see the CREDITS files for
 *  more information)
 *
 *  Imview is Copyrighted (C) 1997-2001 by Hugues Talbot and was
 *  supported in parts by the Australian Commonwealth Science and 
 *  Industry Research Organisation. Please see the COPYRIGHT file 
 *  for full details. Imview also includes the contributions of 
 *  many others. Please see the CREDITS file for full details.
 *
 *  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, USA.
 * */

/*------------------------------------------------------------------------
 *
 * This files complements the imageViewer class by handling
 * the keyboard inputs.
 *
 * The idea is to put together useful shortcuts in additions
 * to the ones provided by the menus.
 *
 * Hugues Talbot	18 Mar 1998
 *      
 *-----------------------------------------------------------------------*/

#include <FL/Fl.H>
#include <assert.h>
#include "imview.hxx"
#include "imageIO.hxx"
#include "pointfile.hxx"
#include "imageViewer.hxx"
#include "menubar.hxx"
#include "server/interpreter.hxx"

extern imageViewer *mainViewer;
extern linkmanager *imview_linkmanager;

extern int appMaxWidth, appMaxHeight;

extern bool disableIOKeys;
extern displaymode displaymodepref;
extern bool fullScreen;

bool imageViewer::toggle_fullscreen(void)
{
    static displaymode olddspmode = displaymodepref; // irrelevant default
    static int  oldx=-1, oldy=-1, oldw=-1, oldh=-1;

    dbgprintf("Toggling fullscreen status\n");

    if (fullScreen) { // undo fullscreen
        dbgprintf("  Undoing fullscreen, reverting to (%d+%d-%dx%d)\n",
                  oldx, oldy, oldw, oldh);
        assert((oldw > 0) && (oldh > 0));
        parentWindow->fullscreen_off(oldx, oldy, oldw, oldh);
	setdisplaymode(olddspmode);
    } else {
        oldx = parentWindow->x(); // incorrect, should be global x()
        oldy = parentWindow->y();
        oldw = parentWindow->w();
        oldh = parentWindow->h();
        dbgprintf("  Going fullscreen, saved dimensions as (%d+%d-%dx%d)\n",
                  oldx, oldy, oldw, oldh);
	olddspmode = getdisplaymode();
	setdisplaymode(IMV_DISPLAY_DECOUPLE_WIN_IMG);
        parentWindow->fullscreen();
    }

    fullScreen = !fullScreen;

    return fullScreen;
}

// handle more keyboard shortcuts
int imageViewer::handleKeyboardEvent()
{
    int retval = 0;
    const char *txt;

    // look for special characters first
    switch (Fl::event_key()) {
    case FL_Escape:
        if (!disableIOKeys) 
            quit_cb(0,0);
	retval = 1;
	break;
	
	/* frame switch */
    case FL_Page_Up:
	dbgprintf("Page up key pressed\n");
	nextframe_cb(0,0);
	retval = 1;
	break;

    case FL_Page_Down:
	dbgprintf("Page down key pressed\n");
	previousframe_cb(0,0);
	retval = 1;
	break;
	
	/* component switch */
    case FL_Home:
	dbgprintf("Home key pressed \n");
	nextcomponent_cb(0,0);
	retval = 1;
	break;

    case FL_End:
	dbgprintf("End key pressed \n");
	previouscomponent_cb(0,0);
	retval = 1;
	break;

	/* 3D switch */
    case FL_Insert:
	dbgprintf("Insert key pressed \n");
	nextplane_cb(0,0);
	retval = 1;
	break;

    case FL_Delete:
	dbgprintf("Delete key pressed \n");
	previousplane_cb(0,0);
	retval = 1;
	break;

    case FL_BackSpace:
	dbgprintf("Backspace key pressed \n");
	previousimage_cb(0,0);
	retval = 1;
	break;
    }

    // then look for normal text
    txt = Fl::event_text();
    dbgprintf("Received keyboard event with text: %s\n", txt);

    switch (txt[0]) {
    case 'C':
    case 'G':
    case 's':
	retval = 0;
	break;

    case 'R': // reset the display (return to default zoom, maximises)
        if (Fl::event_state() & FL_ALT) {
            defaultZoomFactor_ = 1.0;
        }
	unzoom_cb(0,0);
	resetDisplay();
	retval = 1;
	break;	
    case 'c': // close the current image
        if (!disableIOKeys) 
            close_cb(0,0);
	retval = 1;
	break;
    case ' ': // another way to walk the image list 
	if (Fl::event_key(FL_Shift_L) || Fl::event_key(FL_Shift_R))
	    previousimage_cb(0,0);
	else
	    nextimage_cb(0,0);
	retval = 1;
	break;
    case 'f':
	if (!(Fl::event_state() & FL_ALT)) {
	    fullscreen_cb(0,0);
	    retval = 1;
	} // alt-f invokes the file menu.
	break;
    case 'k': // display the next image in list
	nextimage_cb(0,0);
	retval = 1;
	break;
    case 'l': // display the previous image in list
	previousimage_cb(0,0);
	retval = 1;
	break;
    case 'm': // maximise the display
	resetDisplay(false,true);
	retval = 1;
	break;
    case 'n': // return zoom to default value
	unzoom_cb(0,0);
	retval = 1;
	break;
    case 'o': // open a new image
        if (!disableIOKeys) 
            open_cb(0,0);
	retval = 1;
	break;
    case 'p': // closes the point file
        if (!disableIOKeys) 
            closepointfile_cb(0,0);
	retval = 1;
	break;
    case 'q':	// quit the application
        if (!disableIOKeys) 
            quit_cb(0,0);
	retval = 1;
	break;
    case 'r': // redraw the display (do nothing else...)
	redraw();
	retval = 1;
	break;	
    case '.': // zoom in by 10% and grow the window
	if (!(Fl::event_state() & FL_ALT) && (getdisplaymode() == IMV_DISPLAY_WINDOW_FIT_IMG)) {
            // change the DEFAULT zoom factor
            defaultZoomFactor_ = imageZoomFactor_ * 1.1;
	    zoomFactor(defaultZoomFactor_, false); // no redraw
	    resetDisplay(false,true);
	} else 
	    zoomFactor(imageZoomFactor_ * 1.1, true); // maybe redraw
	retval = 1;
	break;
    case '>': // zoom in by 100% and grow the window
	if (!(Fl::event_state() & FL_ALT) && (getdisplaymode() == IMV_DISPLAY_WINDOW_FIT_IMG)) {
            // change the DEFAULT zoom factor
            defaultZoomFactor_ = imageZoomFactor_ * 2.0;
	    zoomFactor(defaultZoomFactor_, false); // no redraw
	    resetDisplay(false,true);
	} else
	    zoomFactor(imageZoomFactor_ * 2.0, true); // maybe redraw
	retval = 1;
	break;
    case ',': // zoom out by 10%
	if (!(Fl::event_state() & FL_ALT) && (getdisplaymode() == IMV_DISPLAY_WINDOW_FIT_IMG)) {
            // change the DEFAULT zoom factor
            defaultZoomFactor_ = imageZoomFactor_ / 1.1;
	    zoomFactor(defaultZoomFactor_, false); // no redraw
	    resetDisplay(false,true);
	} else
	    zoomFactor(imageZoomFactor_ / 1.1, true); // maybe redraw
	retval = 1;
	break;
    case '<': // zoom out by 100%
	if (!(Fl::event_state() & FL_ALT) && (getdisplaymode() == IMV_DISPLAY_WINDOW_FIT_IMG)) {
            // change the DEFAULT zoom factor
            defaultZoomFactor_ = imageZoomFactor_ / 2.0;
	    zoomFactor(defaultZoomFactor_, false); // no redraw
	    resetDisplay(false,true);
	} else {
	    zoomFactor(imageZoomFactor_ / 2.0, true); // maybe redraw
	}
	retval =1;
	break;
    case '[': // next image plane (3d)
	nextplane_cb(0,0);
	retval = 1;
	break;
    case ']': // previous image plane (3d)
	previousplane_cb(0,0);
	retval = 1;
	break;
	
    case '*': // secret!
        if (!disableIOKeys) 
            saveimagelist_cb(0,0);
	retval = 1;
	break;
    }

    
    return retval;
}

// redisplay and resize the image to the max that can be done.
void imageViewer::resetDisplay(bool doRedraw, bool forward)
{
    int realMinWidth, realMinHeight;
 
    // sometimes the scrollbars are a problem
    if (doRedraw)
        destroy_scrollbars();

    realMinWidth = trivmin(appMaxWidth,currentImageWidth());
    realMinHeight = trivmin(appMaxHeight,currentImageHeight());
    dbgprintf("Resetting image to %d x %d\n", realMinWidth, realMinHeight);
    
    if (parentWindow) {
        if (getdisplaymode() != IMV_DISPLAY_IMG_FIT_WINDOW) {
            sizeConstraints(realMinWidth, realMinHeight);
        } 
        sizeParent(Ox + realMinWidth, Oy + realMinHeight);
        if (doRedraw)
            redraw_image();
    }
    if (forward && imview_linkmanager) {
        if (imview_linkmanager->resetDisplay() > 0) {
            dbgprintf("Remote reset display failed\n");
        }
    }

    return;
}


