/*
 * Copyright (C) 2007, 2008  Miriam Ruiz <little_miry@yahoo.es>
 *
 * VersatileBrowser uses ColResizeBrowser, written by Greg Ercolano
 * ColResizeBrowser (C) Greg Ercolano <erco@seriss.com>
 * URL: http://seriss.com/people/erco/fltk/
 * GNU GPL License (version 2 or, at your option, any later version)
 *
 * 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-1307  USA
 */

#ifndef _games_pkgbrowser_h
#define _games_pkgbrowser_h

#include <stdlib.h>

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Browser.H>
#include <FL/Fl_Help_View.H>
#include <FL/fl_draw.H>

#include <string>

//
// Demonstrate how to derive a class extending Fl_Browser with interactively resizable columns
// erco 1.10 12/09/2005
//
class VersatileBrowser : public Fl_Browser
{
    Fl_Color  _colsepcolor;	// color of column separator lines 
    int       _showcolsep;	// flag to enable drawing column separators
    Fl_Cursor _last_cursor;	// saved cursor state info
    int       _dragging;	// 1=user dragging a column
    int       _dragcol;		// col# user is currently dragging
    int      *_widths;		// pointer to user's width[] array
    int       _nowidths[1];	// default width array (non-const)
    // CHANGE CURSOR
    //     Does nothing if cursor already set to value specified.
    //
    void change_cursor(Fl_Cursor newcursor) {
        if ( newcursor != _last_cursor ) {
            fl_cursor(newcursor, FL_BLACK, FL_WHITE);
            _last_cursor = newcursor;
        }
    }
    // RETURN THE COLUMN MOUSE IS 'NEAR'
    //     Returns -1 if none.
    //
    int which_col_near_mouse() {
        int X,Y,W,H;
        Fl_Browser::bbox(X,Y,W,H); // area inside browser's box()
        // EVENT NOT INSIDE BROWSER AREA? (eg. on a scrollbar)
        if ( ! Fl::event_inside(X,Y,W,H) ) {
            return(-1);
        }
        int mousex = Fl::event_x() + hposition();
        int colx = this->x();
        for ( int t=0; _widths[t]; t++ ) {
            colx += _widths[t];
            int diff = mousex - colx;
            // MOUSE 'NEAR' A COLUMN?
            //     Return column #
            //
            if ( diff >= -4 && diff <= 4 ) {
                return(t);
            }
        }
        return(-1);
    }

protected:
    // MANAGE EVENTS TO HANDLE COLUMN RESIZING
    int handle(int e) {
    // Not showing column separators? Use default Fl_Browser::handle() logic
    if ( ! showcolsep() ) return(Fl_Browser::handle(e));
        // Handle column resizing
        int ret = 0;
        switch ( e ) {
            case FL_ENTER: {
                ret = 1;
                break;
            }
            case FL_MOVE: {
                if ( which_col_near_mouse() >= 0 ) {
                    change_cursor(FL_CURSOR_WE);
                } else {
                    change_cursor(FL_CURSOR_DEFAULT);
                }
                ret = 1;
                break;
            }
            case FL_PUSH: {
                int whichcol = which_col_near_mouse();
                if ( whichcol >= 0 ) {
                    // CLICKED ON RESIZER? START DRAGGING
                    ret = 1;
                    _dragging = 1;
                    _dragcol = whichcol;
                    change_cursor(FL_CURSOR_DEFAULT);
                }
                break;
            }
            case FL_DRAG: {
                if ( _dragging ) {
                    ret = 1;
                    // Sum up column widths to determine position
                    int mousex = Fl::event_x() + hposition();
                    int newwidth = mousex - x();
                    for ( int t=0; _widths[t] && t<_dragcol; t++ ) {
                        newwidth -= _widths[t];
                    }
                    if ( newwidth > 0 ) {
                        // Apply new width, redraw interface
                        _widths[_dragcol] = newwidth;
                        if ( _widths[_dragcol] < 2 ) {
                            _widths[_dragcol] = 2;
                        }
                        redraw();
                    }
                }
                break;
            }
            case FL_LEAVE:
            case FL_RELEASE: {
                _dragging = 0; // disable drag mode
                change_cursor(FL_CURSOR_DEFAULT); // ensure normal cursor
                ret = 1;
                break;
            }
        }
        if ( _dragging ) return(1); // dragging? don't pass event to Fl_Browser
        return(Fl_Browser::handle(e) ? 1 : ret);
    }
    void draw() {
        // DRAW BROWSER
        Fl_Browser::draw();
        if ( _showcolsep ) {
            // DRAW COLUMN SEPARATORS
            int colx = this->x() - hposition();
            int X,Y,W,H;
            Fl_Browser::bbox(X,Y,W,H);
            fl_color(_colsepcolor);
            for ( int t=0; _widths[t]; t++ ) {
                colx += _widths[t];
                if ( colx > X && colx < (X+W) ) {
                    fl_line(colx, Y, colx, Y+H-1);
                }
            }
        }
    }
public:
    // CTOR
    VersatileBrowser(int X,int Y,int W,int H,const char*L=NULL) : Fl_Browser(X,Y,W,H,L) {
        _colsepcolor = Fl_Color(FL_GRAY);
        _last_cursor = FL_CURSOR_DEFAULT;
        _showcolsep  = 0;
        _dragging    = 0;
        _nowidths[0] = 0;
        _widths      = _nowidths;
    }
    // GET/SET COLUMN SEPARATOR LINE COLOR
    Fl_Color colsepcolor() const {
        return(_colsepcolor);
    }
    void colsepcolor(Fl_Color val) {
        _colsepcolor = val;
    }
    // GET/SET DISPLAY OF COLUMN SEPARATOR LINES
    //     1: show lines, 0: don't show lines
    //
    int showcolsep() const {
        return(_showcolsep);
    }
    void showcolsep(int val) {
        _showcolsep = val;
    }
    // GET/SET COLUMN WIDTHS ARRAY
    //    Just like fltk method, but array is non-const.
    //
    int *column_widths() const {
        return(_widths);
    }
    void column_widths(int *val) {
        _widths = val;
        Fl_Browser::column_widths(val);
    }
};

class PackageBrowser : public VersatileBrowser
{
public:
	PackageBrowser(int x, int y, int w, int h, const char *l = NULL);
	virtual ~PackageBrowser();
	const std::string pkg_selected(void) const;

protected:
	virtual void item_select(void *p, int s=1);
	virtual int item_width(void *p) const;
	virtual void item_draw(void *p, int x, int y, int w, int h)  const;
	virtual int handle(int e);

private:
	const unsigned int num_bar_images;
	Fl_Image *bar_images[2*2];
	std::string pkgname;
	Fl_Image *find_screenshot(const std::string packagename);
};

class PackageView : public Fl_Help_View
{
public:
	PackageView(int xx, int yy, int ww, int hh, const char *l = 0);

private:
	static const char *link_cb(Fl_Widget *w, const char *uri);
};

#endif
