/*
* File: menu.cc - Menu classes
* Project: GED - bitmap editor (ICP)
* Author: Kamil Dudka, xdudka00
* Team: xdudka00, xfilak01, xhefka00, xhradi08
* Created: 2006-04-08
*/
#include <iostream>
#include <string>
#include <map>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/fl_ask.H>
#include "global.h"
#include "pngimage.h"
#include "pluginsupport.h"
#include "gedconf.h"
#include "command.h"
#include "appwnd.h"
#include "menu.h"
using std::string;
namespace {
/*
* Menu callback functions
*/
void cb_new (Fl_Widget *, void *);
void cb_open (Fl_Widget *, void *);
void cb_save (Fl_Widget *, void *);
void cb_saveas (Fl_Widget *, void *);
void cb_close (Fl_Widget *, void *);
void cb_closeall (Fl_Widget *, void *);
void cb_exit (Fl_Widget *, void *);
void cb_undo (Fl_Widget *, void *);
void cb_redo (Fl_Widget *, void *);
void cb_unselect (Fl_Widget *, void *);
void cb_apphelp (Fl_Widget *, void *);
void cb_dochelp (Fl_Widget *, void *);
void cb_draw (Fl_Widget *, void *);
void cb_gray (Fl_Widget *, void *);
void cb_invert (Fl_Widget *, void *);
void cb_filter (Fl_Widget *, void *);
void cb_load (Fl_Widget *, void *);
void cb_stop (Fl_Widget *, void *);
void cb_mac (Fl_Widget *, void *);
}
/*
* Initialize singleton HelpBrowser
*/
HelpBrowser *HelpBrowser::_instance = 0;
/*
* Global point to singleton HelpBrowser
*/
HelpBrowser *HelpBrowser::ptr ()
{
if (0== _instance)
_instance = new HelpBrowser;
return _instance;
}
/*
* Close help browser
*/
void HelpBrowser::close ()
{
if (0== _instance)
return;
_instance->hide ();
delete _instance;
}
/*
* HelpBrowser destructor
*/
HelpBrowser::~HelpBrowser ()
{
_instance = 0;
}
/*
* Document menu
* pDoc: pointer to document object
* at: position of menu bar
* size: size of menu bar
*/
DocMenu::DocMenu (DocWnd *pDoc, const Point &at, const BoxSize &size):
Fl_Menu_Bar (at.x, at.y, size.width, size.height),
_doc (pDoc)
{
// Submenu file
add ("&File/&New", FL_CTRL + 'n', cb_new, 0);
add ("&File/&Open", FL_CTRL + 'o', cb_open, 0, FL_MENU_DIVIDER);
_iSave = add ("&File/&Save", FL_CTRL + 's', cb_save, _doc);
add ("&File/Save &as", 0, cb_saveas, _doc, FL_MENU_DIVIDER);
add ("&File/Close", FL_CTRL + 'w', cb_close, _doc);
add ("&File/Close all", 0, cb_closeall);
add ("&File/E&xit", FL_CTRL + 'q', cb_exit);
// Submenu Edit
add ("&Edit/Select &all", 0, cb_unselect, _doc, FL_MENU_DIVIDER);
_iUndo = add ("&Edit/&Undo", FL_CTRL + 'z', cb_undo, _doc);
_iRedo = add ("&Edit/&Redo", FL_CTRL + 'y', cb_redo, _doc);
// Submenu Tool
for (int i=1; i<iDrawToolCnt; i++) {
string item ("&Tool/");
item.append (DrawContext::toolLabel (static_cast<EDrawTool>(i)) );
add (item.c_str(), 0, cb_draw);
}
// Submenu Filter (if needed)
add ("&Filter/Grayscale", 0, cb_gray, _doc);
add ("&Filter/Invert", 0, cb_invert, _doc, FL_MENU_DIVIDER);
// Read plugin filters
typedef std::map<string, string> TPluginMap;
TPluginMap &pluginMap = PluginList::ptr()->_pluginNameMap;
const string filterPrefix ("filter:");
for (TPluginMap::iterator i = pluginMap.begin(); i!= pluginMap.end(); i++) {
string item = (*i).first;
if (0!=item.find (filterPrefix))
// Not filter category plugin
return;
item.replace (0, filterPrefix.size(), "Fil&ter/");
add (item.c_str(), 0, cb_filter, _doc);
}
// Submenu Macro
MacroList macList = GedConf::ptr()->getMacroList ();
_iLoad = add ("&Macro/&Load", 0, cb_load, this);
_iStop = add ("&Macro/&Create macro...", 0, cb_stop, this, FL_MENU_INACTIVE | FL_MENU_DIVIDER);
for (MacroList::iterator i= macList.begin(); i!= macList.end(); i++) {
std::string item ("&Macro/");
item.append ((*i).first);
add (item.c_str(), 0, cb_mac, _doc);
}
// Help item on menu bar
add ("&Help", 0, cb_dochelp);
}
/*
* Unused destructor (for now)
*/
DocMenu::~DocMenu ()
{
}
/*
* Application menu
* at: position of menu bar
* size: size of menu bar
*/
AppMenu::AppMenu (const Point &at, const BoxSize &size):
Fl_Menu_Bar (at.x, at.y, size.width, size.height)
{
// Standart menu options
add ("&File/&New", FL_CTRL + 'n', cb_new);
add ("&File/&Open", FL_CTRL + 'o', cb_open, 0, FL_MENU_DIVIDER);
_iCloseAll = add ("&File/Close all", 0, cb_closeall);
add ("&File/E&xit", FL_CTRL + 'q', cb_exit);
add ("&Help", 0, cb_apphelp);
}
void AppMenu::enableCloseAll (bool enable)
{
mode (_iCloseAll, enable ? 0:FL_MENU_INACTIVE);
}
/*
* Unused destructor (for now)
*/
AppMenu::~AppMenu ()
{
}
/*
* enable/disable menu items fro image "img"
*/
void DocMenu::menuInit (Image &img)
{
mode (_iSave, img.needSave() ? 0:FL_MENU_INACTIVE);
mode (_iUndo, img.canUndo() ? 0:FL_MENU_INACTIVE);
mode (_iRedo, img.canRedo() ? 0:FL_MENU_INACTIVE);
}
/*
* Start macro loading
*/
void DocMenu::macLoad ()
{
mode (_iLoad, FL_MENU_INACTIVE);
mode (_iStop, FL_MENU_DIVIDER);
_doc -> macLoad ();
}
/*
* Stop macro laoding
*/
void DocMenu::macStop ()
{
const char *szMacName = fl_input ("New macro name:");
if (0== szMacName || '\0'== *szMacName)
return;
_doc -> macCreate (szMacName);
std::string item ("&Macro/");
item.append (szMacName);
add (item.c_str(), 0, cb_mac, _doc);
mode (_iLoad, 0);
mode (_iStop, FL_MENU_INACTIVE | FL_MENU_DIVIDER);
}
namespace {
/*
* File/New callback
*/
void cb_new (Fl_Widget *, void *)
{
Image *img = new PNGImage (GlobalH::newImageSize);
DocWnd *doc = new Document (img);
doc->show ();
}
/*
* File/Open callback
*/
void cb_open (Fl_Widget *, void *)
{
// Ask for name
char *szImg = fl_file_chooser ("Open image", "Image files (*.png)", 0);
if (NULL==szImg)
return;
try {
// Create image object
Image *img = Image::readImageFromFile (szImg);
// Create image window
Document *doc = new Document (img);
doc -> show ();
}
catch (Image::ErrUnknownFF) {
std::string msg (szImg);
msg.append (": Unknown file format!");
fl_alert (msg.c_str ());
}
catch (Image::ErrLoad) {
std::string msg (szImg);
msg.append (": could not open image!");
fl_alert (msg.c_str ());
}
}
/*
* Save callback
*/
void cb_save (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
try {
pDoc->save();
}
catch (Image::ErrSave) {
fl_alert ("Could not save image!");
}
}
/*
* SaveAs callback
*/
void cb_saveas (Fl_Widget *, void *data)
{
try {
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->saveAs();
}
catch (Image::ErrSave) {
fl_alert ("Could not save image!");
}
}
/*
* Close callback
*/
void cb_close (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->tryClose();
}
/*
* CloseAll callback
*/
void cb_closeall (Fl_Widget *, void *)
{
if (0==fl_choice ("Close all windows?", "No", "Yes", 0))
return;
AppWnd *app = AppWnd::ptr();
if (app->closeAll())
app->show ();
}
/*
* Exit callback
*/
void cb_exit (Fl_Widget *, void *)
{
AppWnd::ptr()->exit();
}
/*
* Undo callback
*/
void cb_undo (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->undo();
}
/*
* Redo callback
*/
void cb_redo (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->redo();
}
/*
* Help callback (called from main window)
*/
void cb_apphelp (Fl_Widget *, void *)
{
std::string helpFile= GedConf::ptr()->getHelpDir() + "/index.html";
HelpBrowser::ptr()->load (helpFile.c_str ());
HelpBrowser::ptr()->show ();
}
/*
* Help callback (called from document window)
*/
void cb_dochelp (Fl_Widget *, void *)
{
std::string helpFile= GedConf::ptr()->getHelpDir() + "/index.html#document";
HelpBrowser::ptr()->load (helpFile.c_str ());
HelpBrowser::ptr()->show ();
}
/*
* Select whole image
*/
void cb_unselect (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->unSelect ();
}
/*
* One of draw items was selected
*/
void cb_draw (Fl_Widget *widget, void *)
{
const Fl_Menu_Item *const item = reinterpret_cast<Fl_Menu_ *>(widget)->mvalue();
AppWnd::ptr()->selectTool (DrawContext::toolByLabel (item->label ()));
}
/*
* Built-in grayscale filter
*/
void cb_gray (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->filterGray ();
}
/*
* Built-in inbert filter
*/
void cb_invert (Fl_Widget *, void *data)
{
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc->filterInvert ();
}
/*
* One of filter items was selected
*/
void cb_filter (Fl_Widget *widget, void *data)
{
const Fl_Menu_Item *const item = reinterpret_cast<Fl_Menu_ *>(widget)->mvalue();
DocWnd *const pDoc = static_cast<DocWnd *>(data);
// Retrieve original plugin name
string pluginName ("filter:");
pluginName.append (item->label ());
pDoc->applyPlugin (pluginName);
}
/*
* One of macro items was selected
*/
void cb_mac (Fl_Widget *widget, void *data)
{
const Fl_Menu_Item *const item = reinterpret_cast<Fl_Menu_ *>(widget)->mvalue();
DocWnd *const pDoc = static_cast<DocWnd *>(data);
pDoc -> applyMacro (item->label ());
}
/*
* Load macro callback
*/
void cb_load (Fl_Widget *, void *data)
{
DocMenu *const menu = static_cast<DocMenu *>(data);
menu->macLoad ();
}
/*
* Stop macro callback
*/
void cb_stop (Fl_Widget *, void *data)
{
DocMenu *const menu = static_cast<DocMenu *>(data);
menu->macStop ();
}
}