Česky
Kamil Dudka

GED 2006 (C++)

File detail

Name:Downloadappwnd.cc [Download]
Location: ged2006 > src
Size:7.5 KB
Last modification:2007-08-29 02:16

Source code

/*
 * File: appwnd.cc - Application window
 * Project: GED - bitmap editor (ICP)
 * Author: Kamil Dudka, xdudka00
 * Team: xdudka00, xfilak01, xhefka00, xhradi08
 * Created: 2006-03-12
 */
 
#include <iostream>
 
#include <string>
#include <sstream>
#include <fstream>
#include <list>
 
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_PNG_Image.H>
 
#include "global.h"
#include "image.h"
#include "menu.h"
#include "gedconf.h"
#include "appwnd.h"
 
using std::string;
 
using GlobalH::szAppName;
using GlobalH::menuBarHeight;
 
namespace {
	const BoxSize wndSize (400, 300);
 
	void cb_wndProc (Fl_Widget *, void *)
	{
		AppWnd::ptr()->exit();
	}
}
 
/*
 * Initialize singleton AppWnd
 */
AppWnd *AppWnd::_instance = 0;
 
/*
 * Sequence number for new documents
 */
int AppWnd::_iNewDocIterator = 1;
 
/*
 * Global point to singleton AppWnd
 */
AppWnd *AppWnd::ptr ()
{
	if (0== _instance)
		_instance = new AppWnd;
 
	return _instance;
}
 
/*
 * This function should be called on program exit
 */
void AppWnd::destroy ()
{
	if (0== _instance)
		return;
 
	_instance -> hide();
	_instance -> clear();
	Fl::delete_widget (_instance);
}
 
/*
 * Return name for new document
 */
string AppWnd::newDocName ()
{
	std::ostringstream name;
	name << "new" << (_iNewDocIterator++) << ".png";
 
	return name.str();
}
 
/*
 * Add document "doc" to list
 */
void AppWnd::addDoc (Document *doc) {
#ifndef NDEBUG
	std::cerr << "Added doc..\n";
#endif
	_docList.push_back (doc);
	_menu -> enableCloseAll (true);
}
 
/*
 * Remove document "doc" from list
 */
void AppWnd::remDoc (Document *doc) {
#ifndef NDEBUG
	std::cerr << "Deleted doc..\n";
#endif
	_docList.remove (doc);
	if (_docList.empty ())
		_menu -> enableCloseAll (false);
}
 
/*
 * Delete all documents
 */
bool AppWnd::closeAll () {
	typedef std::list<Document *> TDocList;
	typedef TDocList::iterator TDocListIter;
 
	TDocList tmp = _docList;
	for (TDocListIter i=tmp.begin(); i!=tmp.end(); i++) {
		// Close doc (ask for save)
		if (! ((*i)->tryClose () ))
			// QueryEndSession canceled by user
			return false;
	}
 
	return true;
}
 
/*
 * Create main (app) window
 */
AppWnd::AppWnd ()
	:Fl_Window (ToolSelect::width-1, ToolSelect::height + 8*menuBarHeight -1, szAppName),
	_drawContext (TOOL_NOTOOL, 3, 8)
{
	this->callback (cb_wndProc);
	this->color (FL_DARK3);
	this->begin ();
 
	// Create menu
	_menu = new AppMenu (Point(0, 0), BoxSize(ToolSelect::width, menuBarHeight));
	_menu -> enableCloseAll (false);
 
	// Create toolbar
	_toolSelect = new ToolSelect (0, menuBarHeight, &(_drawContext.tool));
 
	// Fg brush selection widget
	_fgBrushSelect = new BrushSelect (
			10, ToolSelect::height + 2*menuBarHeight,
			ToolSelect::width-20, 2*menuBarHeight,
			"Foreground brush",
			&(_drawContext.fgBrushWidth),
			&(_drawContext.fgColor));
 
	// Bg brush selection widget
	_bgBrushSelect = new BrushSelect (
			10, ToolSelect::height + 5*menuBarHeight,
			ToolSelect::width-20, 2*menuBarHeight,
			"Background brush",
			&(_drawContext.bgBrushWidth),
			&(_drawContext.bgColor));
 
	this->end ();
}
 
/*
 * AppWnd destructor
 */
AppWnd::~AppWnd ()
{
	_instance = 0;
}
 
/*
 * Close all documents and exit
 */
void AppWnd::exit () {
	if (!closeAll ())
		return;
 
	// Shutdown sequence
	HelpBrowser::close ();
	this->hide ();
	this->clear ();
	Fl::delete_widget (this);
}
 
/*
 * Return true if window is maintained Document
 */
bool AppWnd::isDocument (Fl_Window *ptr)
{
	return _docList.end()!= std::find (
			_docList.begin(),
			_docList.end(),
			static_cast<Document *> (ptr));
}
 
/*
 * Return current DrawTool
 */
DrawContext AppWnd::drawContext () const
{
	return _drawContext;
}
 
/*
 * Set current DrawTool
 */
void AppWnd::selectTool (EDrawTool et)
{
	_drawContext.tool = et;
	_toolSelect -> redraw ();
}
 
/*
 * Create toolbar widget
 */
ToolSelect::ToolSelect (int x, int y, EDrawTool *dt):
	Fl_Pack (x, y, width, height),
	_drawTool (dt)
{
	begin();
	Fl_Button **pButt = _tbButt;
	Fl_PNG_Image **pIcon = _tbIcon;
	for (int currRow = 0; currRow < iRowCnt; currRow++) {
		// Create one line of toolbar
		Fl_Pack *line = new Fl_Pack (0, 0, iColCnt * iButtonSize, iButtonSize);
		line -> type (FL_HORIZONTAL);
		line -> begin();
 
		// Create buttons
		for (int currCol = 0; currCol < iColCnt; currCol++, pButt++, pIcon++) {
			// Button text
			const char *szText = DrawContext::toolLabel(
					static_cast<EDrawTool>(pButt-_tbButt+1));
 
			// Draw button
			*pButt = new Fl_Button (0, 0, iButtonSize, iButtonSize, szText);
 
			(*pButt) -> callback (cb_button, this);
			(*pButt) -> color (FL_WHITE);
 
			// Obtain image name
			std::string iconFile = GedConf::ptr()->getImageDir() + "/" + szText +".png";
 
			// Test if file exists
			std::fstream file (iconFile.c_str(), std::ios::in);
			if (file) {
				file.close ();
 
				// Load image and draw icon
				*pIcon = new Fl_PNG_Image (iconFile.c_str());
				(*pButt) -> image (*pIcon);
			} else
				*pIcon = 0;
		}
 
		line -> end();
	}
	end();
}
 
/*
 * Toolbar destructor
 */
ToolSelect::~ToolSelect ()
{
	this->hide ();
	this->clear ();
	for (int i=0; i<iButtonCnt; i++)
		delete _tbIcon [i];
}
 
/*
 * Toolbar button callback
 */
void ToolSelect::cb_button (Fl_Widget *widget, void *data)
{
 
	Fl_Button *pButt = static_cast<Fl_Button *>(widget);
	ToolSelect *const pTB = static_cast<ToolSelect *>(data);
 
	pTB->setTool (pButt);
	pTB->redraw ();
}
 
/*
 * Set tool corresponding to button "butt"
 */
void ToolSelect::setTool (Fl_Button *butt)
{
	int i=0;
	for (Fl_Button **scan = _tbButt; *scan != butt; scan++, i++)
		if (i>=iButtonCnt)
			// Critical internal error
			throw;
 
	*_drawTool = static_cast<EDrawTool>(i+1);
}
 
/*
 * Redraw toolbar widget
 */
void ToolSelect::redraw ()
{
	for (int i=0; i<iButtonCnt; i++)
		_tbButt [i] -> value ( i+1==*_drawTool ? 1:0);
 
	Fl_Pack::redraw ();
}
 
/*
 * Create brush selection widget
 */
BrushSelect::BrushSelect (int x, int y, int width, int height, const char *szTitle, int *pBrushSize, Pixel *pBrushColor):
	Fl_Pack (x, y, width, height),
	_pBrushSize (pBrushSize),
	_pBrushColor (pBrushColor)
{
	begin();
	_pButt = new Fl_Button (x, y, width, menuBarHeight, szTitle);
	_pButt->callback (cb_button, this);
	setButtonColor ();
 
	_pVal = new Fl_Value_Slider (x, y+menuBarHeight, width, menuBarHeight);
	_pVal->callback (cb_valuator, this);
	_pVal->type (FL_HORIZONTAL);
	_pVal->bounds (1.0,10.0);
	_pVal->precision (0);
	_pVal->value (static_cast<double> (*_pBrushSize));
	end();
}
 
/*
 * Destroy brush selection widget
 */
BrushSelect::~BrushSelect ()
{
	this->hide ();
	this->clear ();
}
 
/*
 * Ask user for color
 */
void BrushSelect::askForColor ()
{
	fl_color_chooser ("Set brush color",
			_pBrushColor->red, _pBrushColor->green, _pBrushColor->blue);
 
	setButtonColor ();
}
/*
 * Set button color to selected color
 */
void BrushSelect::setButtonColor () {
	_pButt->color (fl_rgb_color (
			_pBrushColor->red,
			_pBrushColor->green,
			_pBrushColor->blue));
 
	_pButt->labelcolor (fl_rgb_color (
			0xFF - _pBrushColor->red,
			0xFF - _pBrushColor->green,
			0xFF - _pBrushColor->blue));
}
 
/*
 * Read brush width from valuator
 */
void BrushSelect::readBrushWidht ()
{
	*_pBrushSize = static_cast<int> (_pVal->value ());
}
 
/*
 * Brush selection widget button callback
 */
void BrushSelect::cb_button (Fl_Widget *, void *data)
{
	BrushSelect *const pBS = static_cast<BrushSelect *>(data);
	pBS->askForColor ();
}
 
/*
 * Brush selection widget valuator callback
 */
void BrushSelect::cb_valuator (Fl_Widget *, void *data)
{
	BrushSelect *const pBS = static_cast<BrushSelect *>(data);
	pBS->readBrushWidht ();
}