/*
* $Id: menubar.cxx,v 4.15 2009/05/08 00:49:04 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.
* */
/*------------------------------------------------------------------------
*
* The menu portion of imView, an image viewer program for X11
* by Hugues Talbot 26 Oct 1997
*
* This program is available free of charge for anyone to use under no
* guarantee of any kind, expressed or implied.
*
*-----------------------------------------------------------------------*/
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Sys_Menu_Bar.H> // system menubar (for macs)
#include <FL/Fl_Box.H>
#include <FL/Fl_File_Chooser.H>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "imview.hxx"
#include "imageIO.hxx"
#include "pointfile.hxx"
#include "imageViewer.hxx"
#include "menubar.hxx"
// components of the application
extern imageViewer *mainViewer;
extern char appName[];
extern imViewMenuBar *mainMenuBar;
extern imageIO *IOBlackBox;
extern pointfile *PtFileMngr;
// other global flags
extern int debugIsOn;
extern int stopDebug;
extern bool lutWraparound;
extern volatile bool syncDisplay;
extern bool disableMainMenu;
extern int makeImageCharIfFits;
extern int RGBdisplaysRGB;
extern int fitCharOverAllSamples;
extern int fitCharOverAllSlices;
extern bool hideMainMenu;
extern bool fullScreen;
extern displaymode displaymodepref;
// went the easy way on that one:
extern double persistentGamma;
imViewMenuBar::imViewMenuBar(int x, int y, int w, int h, const char *label)
: Fl_Menu_Bar(x,y,w,h,label)
{
int i, menusize;
Fl_Menu_Item startmenu[] = { // this menu is only temporary
{"&File", 0, 0, 0, FL_SUBMENU},
{"Open", FL_COMMAND+'o', open_cb},
{OPEN_AS_RAW, FL_COMMAND+FL_SHIFT+'o', openraw_cb},
{CLOSE_ITEM, FL_COMMAND+'c', close_cb, 0, FL_PUP_GREY},
{SAVE_ITEM, FL_COMMAND+'s', save_cb, 0, FL_PUP_GREY},
{OVERLAY_SUBMENU, 0, 0, 0, FL_PUP_GREY | FL_SUBMENU | FL_MENU_DIVIDER},
{OPEN_OVERLAY_ITEM, FL_ALT+'v', openoverlay_cb, 0, 0},
{CLOSE_OVERLAY_ITEM, FL_ALT+'c', closeoverlay_cb, 0, 0},
{0},
{PRINTPREFS_ITEM, FL_COMMAND+FL_SHIFT+'p', printprefs_cb, 0, FL_PUP_GREY | FL_MENU_DIVIDER},
{"Quit", FL_COMMAND+'q', quit_cb},
{0},
{"&Edit", 0, 0, 0, FL_SUBMENU},
{"Undo", 0, test_cb, 0, FL_PUP_GREY},
{"Quick &options", 0, 0, 0, FL_SUBMENU},
{"Display mode", 0, 0, 0, FL_SUBMENU},
{WIN_FIT_IMG_ITEM, 0, displaymode_cb, (void*)IMV_DISPLAY_WINDOW_FIT_IMG, FL_MENU_RADIO | (displaymodepref == IMV_DISPLAY_WINDOW_FIT_IMG) ? FL_MENU_VALUE:0},
{IMG_FIT_WIN_ITEM, 0, displaymode_cb, (void*)IMV_DISPLAY_IMG_FIT_WINDOW, FL_MENU_RADIO | (displaymodepref == IMV_DISPLAY_IMG_FIT_WINDOW) ? FL_MENU_VALUE:0},
{DECOUPLE_IMG_WIN_ITEM, 0, displaymode_cb, (void*)IMV_DISPLAY_DECOUPLE_WIN_IMG, FL_MENU_RADIO | FL_MENU_DIVIDER | (displaymodepref == IMV_DISPLAY_DECOUPLE_WIN_IMG) ? FL_MENU_VALUE:0},
{"Fullscreen", 0, preference_cb, (void *)PREF_FULLSCREEN, FL_PUP_BOX | (fullScreen ? FL_MENU_VALUE:0)},
{0},
{"Hide main menu bar", FL_COMMAND+'m', preference_cb, (void *)PREF_HIDEMENU, FL_PUP_BOX | (hideMainMenu ? FL_MENU_VALUE:0)},
{WRAPLUT_ITEM, 0, preference_cb, (void *)PREF_WRAPAROUND, FL_PUP_BOX | (lutWraparound ? FL_MENU_VALUE:0)},
{SYNCDISP_ITEM, 0, preference_cb, (void *)PREF_SYNCDISP, FL_PUP_BOX | (syncDisplay ? FL_MENU_VALUE:0)},
{"Cast to CHAR if possible", 0, preference_cb, (void *)PREF_MAKECHAR, FL_PUP_BOX | (makeImageCharIfFits ? FL_MENU_VALUE:0)},
{"RGB images display as RGB", 0, preference_cb, (void *)PREF_RGBRGB, FL_PUP_BOX | (RGBdisplaysRGB ? FL_MENU_VALUE:0) },
{"Fit to CHAR over all samples", 0, preference_cb, (void *)PREF_FITALL, FL_PUP_BOX | (fitCharOverAllSamples ? FL_MENU_VALUE:0) },
{"Fit to CHAR over all slices (3D)", 0, preference_cb, (void *)PREF_FIT3D, FL_PUP_BOX | (fitCharOverAllSlices ? FL_MENU_VALUE:0) | FL_MENU_DIVIDER },
// {"Smooth when zooming out", 0, preference_cb, (void *)PREF_SMOOTHUNZOOM, FL_PUP_BOX},
{"Show warnings", FL_COMMAND+FL_SHIFT+'w', preference_cb, (void *)PREF_WARNING, 0},
{"Enable debug messages", FL_ALT+FL_SHIFT+'g', preference_cb, (void *)PREF_DEBUG, FL_PUP_BOX | (debugIsOn? FL_MENU_VALUE:0)},
{"Stop after debug messages", FL_ALT+FL_SHIFT+'s', preference_cb, (void *)PREF_STOPDEBUG, FL_PUP_BOX | (stopDebug ? FL_MENU_VALUE:0)},
// {"Keep points when switching images", FL_ALT+'K', preference_cb, (void *)PREF_KEEPPOINTS, FL_PUP_BOX | FL_MENU_DIVIDER},
// {"Change XOR value for lines...", 0, setxorvalue_cb, 0, 0},
{0},
{"&User preferences...", 0, userprefspanel_cb},
{0},
{"&Transform", 0, 0, 0, FL_SUBMENU},
{"Toolbar...", FL_COMMAND+FL_SHIFT+'t', toolbar_cb, 0, FL_MENU_DIVIDER},
{COLOURMAP_ITEM, 0, 0, 0, FL_PUP_GREY | FL_SUBMENU},
{CLUT_LIST_BEGIN, FL_COMMAND+FL_SHIFT+'c', noclut_cb, 0, 0},
/* rest of CLUT list comes here */
{0},
{"Zoom", 0, 0, 0, FL_SUBMENU},
{"Zoom in 100%", FL_COMMAND+'>', zoomin_cb},
{"Zoom in 10%", FL_COMMAND+'.', smallzoomin_cb},
{"Zoom out 100%", FL_COMMAND+'<', zoomout_cb},
{"Zoom out 10%", FL_COMMAND+',', smallzoomout_cb},
{"Set this zoom factor as default", FL_COMMAND+'\'', thiszoom_cb},
{"Select zoom factor...", FL_COMMAND+'z', selectzoom_cb},
{"Select default zoom factor...", FL_COMMAND+FL_SHIFT+'z', selectdefaultzoom_cb},
{"Apply default zoom factor", FL_COMMAND+'n', unzoom_cb},
{0},
{"Rotate", 0, 0, 0, FL_SUBMENU},
{"Right 90 degree", FL_COMMAND+'(', rotate90right_cb},
{"Left 90 degree", FL_COMMAND+')', rotate90left_cb},
{"180 degree", FL_COMMAND+'+', rotate180_cb},
{ROTATE3DMENU_ITEM, 0, 0, 0, FL_SUBMENU|FL_PUP_INVISIBLE},
{"Up 90 degree", 0, rotate3dup_cb},
{"Down 90 degree", 0, rotate3ddown_cb},
{0},
{0},
{"Flip", 0, 0, 0, FL_SUBMENU},
{"Vertically", FL_COMMAND+'|', flipv_cb},
{"Horizontally", FL_COMMAND+'_', fliph_cb},
{0},
{"Pointfile", 0, 0, 0, FL_SUBMENU},
{"Add point mode", FL_ALT+'g', mode_cb, (void *)MODE_POINTFILE, FL_PUP_BOX | FL_MENU_DIVIDER},
{"Open existing pointfile...", FL_ALT+'p', openpointfile_cb},
{"New pointfile", FL_COMMAND+'p', newpointfile_cb},
{"Save current pointfile", FL_COMMAND+FL_SHIFT+'p', closepointfile_cb},
{"Delete all points", FL_COMMAND+FL_SHIFT+'d', deleteallpoints_cb},
{"Delete last point", FL_COMMAND+'d', deletelastpoint_cb},
{0},
{"Histogram", 0, 0, 0, FL_SUBMENU},
{"Contrast-Brightness", FL_COMMAND+'b', transfer_cb},
{RGBTRANSFER_ITEM, FL_COMMAND+FL_SHIFT+'b', transferRGB_cb, 0, FL_PUP_INVISIBLE},
{BIVHIST_ITEM, FL_COMMAND+'L', showbivhist_cb, 0, FL_PUP_INVISIBLE},
{"Interactive thresholding", FL_COMMAND+'h', threshold_cb, 0, FL_PUP_GREY},
{0},
{0},
{"&Image", 0, 0, 0, FL_SUBMENU},
{"Information...",FL_COMMAND+FL_SHIFT+'i', imageinfo_cb},
{"1-D profile...", FL_COMMAND+'1', showprofile_cb, 0, FL_MENU_DIVIDER},
{"Server", 0, 0, 0, FL_SUBMENU|FL_MENU_DIVIDER},
{"Progress", 0, showprogress_cb, 0, 0},
{"Start", 0, startserver_cb, 0, FL_PUP_INVISIBLE},
{"Stop", 0, stopserver_cb, 0, FL_PUP_INVISIBLE},
{0},
#ifdef MACOSX_CARBON // layout is sufficiently different
{VIEW3D_ITEM, FL_ALT+'3', showview3d_cb, 0, FL_PUP_INVISIBLE|FL_MENU_DIVIDER},
{HYPERSPECTRAL_ITEM, FL_COMMAND+FL_SHIFT+'s', showspectrum_cb, 0, FL_PUP_INVISIBLE},
{NEXTCOMPONENT_ITEM, FL_COMMAND+'2', nextcomponent_cb, 0, FL_PUP_INVISIBLE},
{PREVIOUSCOMPONENT_ITEM, FL_COMMAND+'3', previouscomponent_cb, 0, FL_PUP_INVISIBLE},
{SELECTCOMPONENT_ITEM, FL_COMMAND+'4', selectcomponent_cb, 0, FL_PUP_INVISIBLE | FL_MENU_DIVIDER},
{DEPTHPROFILE_ITEM, FL_COMMAND+FL_SHIFT+'d', showdepthprofile_cb, 0, FL_PUP_INVISIBLE},
{NEXTPLANE_ITEM, FL_COMMAND+'5', nextplane_cb, 0, FL_PUP_INVISIBLE},
{PREVIOUSPLANE_ITEM, FL_COMMAND+'6', previousplane_cb, 0, FL_PUP_INVISIBLE},
{SELECTPLANE_ITEM, FL_COMMAND+'7', selectplane_cb, 0, FL_PUP_INVISIBLE | FL_MENU_DIVIDER},
{NEXTFRAME_ITEM, FL_COMMAND+'8', nextframe_cb, 0, FL_PUP_INVISIBLE},
{PREVIOUSFRAME_ITEM, FL_COMMAND+'9', previousframe_cb, 0, FL_PUP_INVISIBLE},
{SELECTFRAME_ITEM, FL_COMMAND+'0', selectframe_cb, 0, FL_PUP_INVISIBLE | FL_MENU_DIVIDER},
{NEXTIMAGE_ITEM, ' ', nextimage_cb, 0, FL_PUP_GREY},
{PREVIOUSIMAGE_ITEM, FL_SHIFT+' ', previousimage_cb, 0, FL_PUP_GREY | FL_MENU_DIVIDER},
{IMAGE_LIST_BEGIN, 0, 0, 0, FL_PUP_GREY | FL_SUBMENU},
#else
{VIEW3D_ITEM, FL_COMMAND+'3', showview3d_cb, 0, FL_PUP_INVISIBLE|FL_MENU_DIVIDER},
{HYPERSPECTRAL_ITEM, FL_COMMAND+FL_SHIFT+'s', showspectrum_cb, 0, FL_PUP_INVISIBLE},
{NEXTCOMPONENT_ITEM, FL_Home, nextcomponent_cb, 0, FL_PUP_INVISIBLE},
{PREVIOUSCOMPONENT_ITEM, FL_End, previouscomponent_cb, 0, FL_PUP_INVISIBLE},
{SELECTCOMPONENT_ITEM, FL_Scroll_Lock, selectcomponent_cb, 0, FL_PUP_INVISIBLE | FL_MENU_DIVIDER},
{DEPTHPROFILE_ITEM, FL_COMMAND+FL_SHIFT+'d', showdepthprofile_cb, 0, FL_PUP_INVISIBLE},
{NEXTPLANE_ITEM, FL_Insert, nextplane_cb, 0, FL_PUP_INVISIBLE},
{PREVIOUSPLANE_ITEM, FL_Delete, previousplane_cb, 0, FL_PUP_INVISIBLE},
{SELECTPLANE_ITEM, FL_Print, selectplane_cb, 0, FL_PUP_INVISIBLE | FL_MENU_DIVIDER},
{NEXTFRAME_ITEM, FL_Page_Up, nextframe_cb, 0, FL_PUP_INVISIBLE},
{PREVIOUSFRAME_ITEM, FL_Page_Down, previousframe_cb, 0, FL_PUP_INVISIBLE},
{SELECTFRAME_ITEM, FL_Pause, selectframe_cb, 0, FL_PUP_INVISIBLE | FL_MENU_DIVIDER},
{NEXTIMAGE_ITEM, ' ', nextimage_cb, 0, FL_PUP_GREY},
{PREVIOUSIMAGE_ITEM, FL_SHIFT+' ', previousimage_cb, 0, FL_PUP_GREY | FL_MENU_DIVIDER},
{IMAGE_LIST_BEGIN, 0, 0, 0, FL_PUP_GREY | FL_SUBMENU},
#endif
/* originally empty image list goes here */
{0},
{0},
#ifdef IMVIEW_USES_REGISTRATION
/// Work of Charlotte Rozak
/////////////////////////////////////////
{"&Registration",0,0,0,FL_SUBMENU},
{"Methode1",FL_COMMAND+'R',showregisterpanel_cb,0,0},
{0},
#endif
{"&Help", 0, 0, 0, FL_SUBMENU},
{"About imview...", 0, whodunit_cb, 0, FL_MENU_DIVIDER},
{"Quick online help", '?', onlinehelp_cb, 0, 0},
{"Full HTML documentation", FL_COMMAND+'?', fulldocument_cb, 0, FL_MENU_DIVIDER},
{"Licence...", 0, licence_cb, 0, 0},
{"No warranty...", 0, warranty_cb, 0, 0},
{0},
{0}
};
dbgprintf("imViewMenuBar constructed\n");
// set things up for the image list
listName[IMAGE_LIST_ID] = IMAGE_LIST_BEGIN;
listCallback[IMAGE_LIST_ID] = (void *)image_cb;
// set things up for the colour LUT list
listName[CLUT_LIST_ID] = CLUT_LIST_BEGIN;
listCallback[CLUT_LIST_ID] = (void *)clut_cb;
// Create the start menu
menu(startmenu);
// allocated the dynamic menu
menusize = size();
dbgprintf("Menu size = %d\n", menusize);
dynamicMenu = new Fl_Menu_Item[menusize];
for (i = 0 ; i < menusize ; i++) {
dynamicMenu[i] = startmenu[i];
if (disableMainMenu) {
dynamicMenu[i].flags |= FL_MENU_INACTIVE;
}
}
menu(dynamicMenu); // from now on we can forget about the old menu
nbImagesInList = 0;
return;
}
imViewMenuBar::~imViewMenuBar()
{
delete[] dynamicMenu;
dbgprintf("Menu bar destructor called\n");
}
// The System menu can currently be set only once
// Call this to set it, once the main menu has been
// put together relatively completely.
void imViewMenuBar::setSysMenu(void)
{
int menusize = size();
staticMenu_ = new Fl_Menu_Item[menusize];
for (int i = 0 ; i < menusize ; ++i) {
// copy and activate
staticMenu_[i] = dynamicMenu[i];
staticMenu_[i].flags &= ~(FL_PUP_GREY | FL_MENU_INACTIVE);
}
sysmenu_ = new Fl_Sys_Menu_Bar(x(),y(),w(),h());
sysmenu_->menu(staticMenu_);
return;
}
void imViewMenuBar::draw()
{
// if (hideMainMenu)
// resize(x(),y(),w(),0); // ??
//else
// resize(x(),y(),w(),MENUHEIGHT);
Fl_Menu_Bar::draw();
}
// returns 1 if the item is effectively added to the list
// 0 otherwise (item already in item list or invalid)
int imViewMenuBar::addToItemList(const char *newImagePath, int listID)
{
int i, j, res = 0;
int newSize;
const char *shortname;
Fl_Menu_Item *oldMenu;
IMAGEPARM *itx;
if ((newImagePath[0] != '\0') && (!isAlreadyInItemList(newImagePath,listID))) {
oldMenu = dynamicMenu;
dbgprintf("adding %s to the %s list\n", newImagePath, listName[listID]);
newSize = size() + 1;
dbgprintf("Menu will have %d items\n", newSize);
dynamicMenu = new Fl_Menu_Item[newSize];
for (i = 0, j = 0 ; i < newSize-1 ; i++, j++) {
dynamicMenu[j] = oldMenu[i];
if ((oldMenu[i].label() != 0) && (strcmp(oldMenu[i].label(), listName[listID]) == 0)) {
// activate the current item
dynamicMenu[j].flags &= ~FL_MENU_INACTIVE;
i++; j++; // go to the next field
// look for the `0' finishing the menu
for ( ; i < newSize-1 ; i++, j++) {
dynamicMenu[j] = oldMenu[i]; // keep filling the menu
if ((dynamicMenu[j].label() != 0)
&& (dynamicMenu[j].callback() == (Fl_Callback *)listCallback[listID])) {
// uncheck the check box for those items
dynamicMenu[j].flags &= ~FL_PUP_CHECK;
} else
break;
}
// fill the new struct by hand
itx = new IMAGEPARM;
itx->itempath = strdup(newImagePath);
itx->clutpath = 0;
itx->ovlpath = 0;
itx->pfpath = 0;
itx->gamma = persistentGamma; // may not be 1.0!
itx->contrast = 0.5;
itx->brightness = 0.5;
itx->Rgamma = itx->Ggamma = itx->Bgamma = itx->gamma;
itx->Rcontrast = itx->Gcontrast = itx->Bcontrast = itx->contrast;
itx->Rbrightness = itx->Gbrightness = itx->Bbrightness = itx->brightness;
itx->zslice = 0;
itx->comp = 0;
itx->frame = 0;
itx->nbframes = 0;
itx->angle = 0;
itx->mirror = 0;
itx->next = 0;
shortname = strrchr(itx->itempath, '/'); // look for the last `/'
if (shortname == NULL)
shortname = itx->itempath; // revert to full name if name is local
else
shortname++; // go beyond the last `/'
dynamicMenu[j+1] = oldMenu[i];
dynamicMenu[j] = dynamicMenu[0]; // to reset all the fields
dynamicMenu[j].label(shortname);
dynamicMenu[j].shortcut(0);
dynamicMenu[j].callback((Fl_Callback *)(listCallback[listID]));
dynamicMenu[j].user_data((void *)itx);
dynamicMenu[j].flags = (FL_PUP_BOX | FL_PUP_CHECK);
// advance to the next one
j++;
}
}
// specific issue for separate lists
if (listID == IMAGE_LIST_ID) {
// we have positively added an item to the image menu, therefore
// the `close' item can be enabled
setFlagsByName(CLOSE_ITEM, 0, dynamicMenu, newSize);
setFlagsByName(SAVE_ITEM, 0, dynamicMenu, newSize);
setFlagsByName(OVERLAY_SUBMENU, FL_SUBMENU | FL_MENU_DIVIDER, dynamicMenu, newSize);
setFlagsByName(PRINTPREFS_ITEM, FL_MENU_DIVIDER, dynamicMenu, newSize);
// as well as the colour map button
setFlagsByName(COLOURMAP_ITEM, FL_SUBMENU, dynamicMenu, newSize);
// increase the counter of images in the list
nbImagesInList++;
}
delete[] oldMenu;
menu(dynamicMenu);
int sz = size();
dbgprintf("Menu size is now: %d\n", sz);
redraw();
res = 1; // yes, we have added an item
} else { // isAlreadyInItemList(newImagePath,listID) is true
// either the image is already in the image list: we only have to check the right item
// or the newImagePath argument is the empty string. In this case
// we want to unselect all the items.
int sz = size();
for (i = 0 ; i < sz ; i++) {
if ((dynamicMenu[i].label() != 0)
&& (dynamicMenu[i].callback() == (Fl_Callback *)listCallback[listID])) {
dynamicMenu[i].flags &= ~FL_PUP_CHECK;
if (((unsigned long) dynamicMenu[i].user_data() > LAST_INT_ARG)
&& (strcmp((char*)((IMAGEPARM *)dynamicMenu[i].user_data())->itempath, newImagePath) == 0))
dynamicMenu[i].flags |= FL_PUP_CHECK;
}
}
}
return res;
}
void imViewMenuBar::removeFromItemList(const char *oldImagePath, int listID)
{
int i, j;
int newSize;
Fl_Menu_Item *oldMenu;
char *to_be_freed_later = 0;
if (isAlreadyInItemList(oldImagePath,listID)) {
// this is fine, we can remove it from the list!
oldMenu = dynamicMenu;
dbgprintf("removing %s from the image list\n", oldImagePath);
newSize = size() - 1 ;
dbgprintf("Menu will have %d items\n", newSize);
dynamicMenu = new Fl_Menu_Item[newSize];
for (i = 0, j = 0 ; i <= newSize ; i++, j++) {
if (((unsigned long)oldMenu[i].user_data() > LAST_INT_ARG)
&& (strcmp(((IMAGEPARM *)oldMenu[i].user_data())->itempath, oldImagePath) == 0)) {
// now selects the closest image in the image list
if (oldMenu[i+1].label() != 0) {
// the next image down the list gets selected
oldMenu[i+1].flags |= (FL_PUP_BOX | FL_PUP_CHECK); // copy to dynamicMenu will occur later
} else if ((oldMenu[i-1].label() != 0) && (strcmp(oldMenu[i-1].label(), listName[listID]) != 0)) {
// the previous image up the list gets selected
dynamicMenu[i-1].flags |= (FL_PUP_BOX | FL_PUP_CHECK);
} else {
// the image we remove was the last on the list, disable `Image' menu
dynamicMenu[i-1].flags |= (FL_PUP_GREY);
if (listID == IMAGE_LIST_ID) {
// disable the `close' item
setFlagsByName(CLOSE_ITEM, FL_PUP_GREY, dynamicMenu, newSize);
setFlagsByName(SAVE_ITEM, FL_PUP_GREY, dynamicMenu, newSize);
setFlagsByName(OVERLAY_SUBMENU, FL_PUP_GREY | FL_SUBMENU | FL_MENU_DIVIDER, dynamicMenu, newSize);
setFlagsByName(PRINTPREFS_ITEM, FL_PUP_GREY | FL_MENU_DIVIDER, dynamicMenu, newSize);
// and the Colourmap item
setFlagsByName(COLOURMAP_ITEM, FL_PUP_GREY | FL_SUBMENU, dynamicMenu, newSize);
}
}
// this had been strdup'ed
IMAGEPARM *pp = (IMAGEPARM *)oldMenu[i].user_data();
if (pp->itempath != oldImagePath) { // we need the old path a bit longer.
free(pp->itempath);
pp->itempath = 0;
} else {
to_be_freed_later = pp->itempath; // man, isn't that dangerous?
}
if (pp->ovlpath) {
free(pp->ovlpath);
pp->ovlpath = 0;
}
if (pp->pfpath) {
free(pp->pfpath);
pp->pfpath = 0;
}
// this had been new'ed
delete (IMAGEPARM *)oldMenu[i].user_data();
//oldMenu[i].argument = 0; // otherwise FL will think it is still there...
//oldMenu[i].text = 0; // this was a substring allocated in the argument
// skip the name
i++;
}
// business as usual
dynamicMenu[j] = oldMenu[i];
}
delete[] oldMenu;
menu(dynamicMenu);
int sz = size();
dbgprintf("Menu size after deletion is now: %d\n", sz);
// one more dangerous thing to do
if (to_be_freed_later != 0) {
free(to_be_freed_later);
to_be_freed_later = 0;
}
redraw();
}
// we've got nothing to do, the name in question is not in the list
return;
}
int imViewMenuBar::isAlreadyInItemList(const char *newImagePath, int listID)
{
int res = 0;
int i;
dbgprintf("Checking if new name already in %s\n", listName[listID]);
if (newImagePath) { // check that a name was actually given...
for (i = 0 ; i < size() ; i++)
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
if (i != size()) {
for ( ; (unsigned long)dynamicMenu[i].user_data() > LAST_INT_ARG ; i++) {
if (strcmp(((IMAGEPARM *)dynamicMenu[i].user_data())->itempath, newImagePath) == 0) {
dbgprintf("Name %s is already in list at position %d\n",
newImagePath, i);
res = 1; // the new name is already in the list
break;
}
}
}
}
return res;
}
// return the first item matching the given label
void *imViewMenuBar::getItemByLabel(const char *givenLbl, int listID)
{
void *res = 0;
int i;
dbgprintf("Looking for %s in list %s\n", givenLbl, listName[listID]);
if (givenLbl) { // check that a name was actually given...
for (i = 0 ; i < size() ; i++)
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
if (i != size()) {
for ( ; (unsigned long)dynamicMenu[i].user_data() > LAST_INT_ARG ; i++) {
if (strcmp(dynamicMenu[i].label(), givenLbl) == 0) {
dbgprintf("Found %s in list at position %d\n",
givenLbl, i);
res = (void*)dynamicMenu[i].user_data(); // the label was found, first item returned.
break;
}
}
}
}
return res;
}
char *imViewMenuBar::getItemListContent(int listID, int &nbitems)
{
int i, j, outlength, sz;
char *res = 0;
nbitems = 0;
dbgprintf("Saving the content of list #%d to a string\n", listID);
sz = size();
for (i = 0 ; i < sz ; i++)
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
if (i != size()) {
for (j = i, outlength = 0 ; (unsigned long)dynamicMenu[j].user_data() > LAST_INT_ARG ; j++)
outlength += strlen(((IMAGEPARM *)dynamicMenu[j].user_data())->itempath);
if (outlength > 0) {
res = new char[outlength+j+1];
res[0] = '\0';
for (j = i ; (unsigned long)dynamicMenu[j].user_data() > LAST_INT_ARG ; j++) {
strcat(res, ((IMAGEPARM *)dynamicMenu[j].user_data())->itempath);
strcat(res, "\n");
nbitems++;
}
}
}
return res;
}
void *imViewMenuBar::getSelectedItemArgument(int listID)
{
void *res = 0;
int i, sz;
dbgprintf("Looking for path of image being currently selected\n");
sz = size();
// look for where the image list begins
for (i = 0 ; i < sz; i++) {
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
}
if (i != sz) {
for ( ; dynamicMenu[i].label() != 0 ; i++) {
if (dynamicMenu[i].flags == (FL_PUP_BOX | FL_PUP_CHECK)) {
res = (void *)dynamicMenu[i].user_data(); // the new name is already in the list
break;
}
}
}
return res;
}
Fl_Menu_Item *imViewMenuBar::getSelectedMenuItem(int listID)
{
int i;
Fl_Menu_Item *res = 0;
dbgprintf("Looking for menu item currently selected in list %s\n", listName[listID]);
// look for where the image list begins
for (i = 0 ; i < size(); i++)
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
if (i != size()) {
for ( ; dynamicMenu[i].label() != 0 ; i++) {
if (dynamicMenu[i].flags == (FL_PUP_BOX | FL_PUP_CHECK)) {
res = dynamicMenu+i; // the new name is already in the list
break;
}
}
}
return res;
}
// returns the argument to the next image in the image list if possible
// else returns the argument to the first image, and otherwise returns NULL
void *imViewMenuBar::getNextItemInList(int listID)
{
void *res = 0;
int i, startimage;
// look for where the image list begins
for (i = 0 ; i < size(); i++)
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
startimage = i;
if (i != size()) {
for ( ; dynamicMenu[i].label() != 0 ; i++) {
// look for the image name that is currently checked
if (dynamicMenu[i].flags == (FL_PUP_BOX | FL_PUP_CHECK)) {
if (dynamicMenu[i+1].label() != 0)
res = (void *)dynamicMenu[i+1].user_data(); // open next one on the list
else if (dynamicMenu[startimage].label() != 0)
res = (void *)dynamicMenu[startimage].user_data(); // open first image on the list
break;
}
}
}
return res;
}
// returns the path to the next image in the image list if possible
// else returns the path to the first image, and otherwise returns NULL
void *imViewMenuBar::getPreviousItemInList(int listID)
{
void *res = 0;
int i, lastimage, checkedimage;
// look for where the image list begins
for (i = 0 ; i < size(); i++)
if ((dynamicMenu[i].label() != 0) && (strcmp(dynamicMenu[i].label(), listName[listID]) == 0)) {
i++;
break;
}
checkedimage = 0;
// look for the last image
for ( ; dynamicMenu[i].label() != 0 ; i++) {
if (dynamicMenu[i].flags == (FL_PUP_BOX | FL_PUP_CHECK)) {
checkedimage = i;
}
}
lastimage = i-1;
if (checkedimage != 0) {
if ((dynamicMenu[checkedimage-1].label() != 0) && (strcmp(dynamicMenu[checkedimage-1].label(), listName[listID]) != 0))
res = (void *)dynamicMenu[checkedimage-1].user_data(); // open previous one on the list
else if (dynamicMenu[lastimage].label() != 0)
res = (void *)dynamicMenu[lastimage].user_data(); // open last image on the list
else
res = 0;
}
return res;
}
// this functions hunts for a named menu element and returns its flags
int imViewMenuBar::getFlagsByName(const char *theName, Fl_Menu_Item *currentMenu, int menuSize)
{
int i, theFlags = -1;
if (currentMenu == 0)
currentMenu = dynamicMenu;
if (menuSize == 0)
menuSize = size();
for (i = 0 ; i < menuSize ; i++)
if ((currentMenu[i].label() != 0) && (strcmp(currentMenu[i].label(), (char *)theName) == 0)) {
theFlags = currentMenu[i].flags;
break; // only change the first occurence... Normally no two menu items have the same name
}
return theFlags;
}
// this functions hunts for a named menu element and changes its flags
void imViewMenuBar::setFlagsByName(const char *theName, int theFlags, Fl_Menu_Item *currentMenu, int menuSize)
{
int i;
if (currentMenu == 0)
currentMenu = dynamicMenu;
if (menuSize == 0)
menuSize = size();
for (i = 0 ; i < menuSize ; i++)
if ((currentMenu[i].label() != 0) && (strcmp(currentMenu[i].label(), (char *)theName) == 0)) {
currentMenu[i].flags = theFlags;
break; // only change the first occurence... Normally no two menu items have the same name
}
return;
}