/**
 * @file
 * @brief Contains Fl_Manual_Group layout widget.
 *
 * Copyright 2016 gnuwimp@gmail.com
 * Released under the GNU General Public License v3.0
 */

#include <FL/Fl_Manual_Group.H>
#include <FL/Fl.H>
#include <FL/fl_ask.H>
#include <FL/fl_draw.H>

/**
 * @brief Create a manual layout group.
 *
 * It uses "font" units to resize child widgets.<br>
 * A font unit is the same as current font size for the layout widget.<br>
 * Override layout() method and resize child widgets with set_size() call.<br>
 * Start layout widget with one of start_from_ calls.<br>
 *
 * @param X    [in] X position, relative to window.
 * @param Y    [in] Y position, relative to window.
 * @param W    [in] Width in pixels.
 * @param H    [in] Height in pixels.
 * @param l    [in] Widget label, default 0.
 */
Fl_Manual_Group::Fl_Manual_Group(int X, int Y, int W, int H, const char* l) : Fl_Group(X, Y, W, H, l) {
    end();
    clip_children(1);
}

/**
 * @brief Move to next row, up or down.
 *
 * @param height [in] Height in font units, depending on start_ mode you will go up or down, default 2.
 */
void Fl_Manual_Group::next_row(int height) {
    if (from_right == true) {
        x0 = x2;
    }
    else {
        x0 = x1;
    }

    if (from_bottom) {
        y0 -= (space + (height * font));
    }
    else {
        y0 += (space + (height * font));
    }
}

/**
 * @brief Resize widget and all child widgets.
 *
 * Overrides Fl_Group::resize.<br>
 * Calls Fl_Manual_Group::layout().
 *
 * @param X [in] X position, relative to window.
 * @param Y [in] Y position, relative to window.
 * @param W [in] Width in pixels.
 * @param H [in] Height in pixels.
 */
void Fl_Manual_Group::resize(int X, int Y, int W, int H) {
    Fl_Group::resize(X, Y, W, H);
    resize();
}

/**
 * @brief Resize child widget.
 *
 * @param widget [in] Widget to resize.
 * @param width  [in] Width in font units (0 means all available width for current row).
 * @param height [in] Height in font units (0 means all available height for current row).
 */
void Fl_Manual_Group::set_size(Fl_Widget* widget, int width, int height) {
    if (widget == 0 || width < 0 || height < 0) return;

    int tmpWidth  = 0;
    int tmpHeight = 0;

    if (width == 0) {
        if (from_right == true) {
            tmpWidth = x0 - x1;
        }
        else {
            tmpWidth = x2 - x0;
        }
    }
    else {
        int tmpw = width * font;

        if (from_right == true && x0 - tmpw < x1) {
            tmpWidth = x0 - x1;
        }
        else if (from_right == false && tmpw + x0 > x2) {
            tmpWidth = x2 - x0;
        }
        else {
            tmpWidth = tmpw;
        }
    }

    if (height == 0) {
        if (from_bottom == true) {
            tmpHeight = y0 - y1;
        }
        else {
            tmpHeight = y2 - y0;
        }
    }
    else {
        int tmph = height * font;

        if (from_bottom == true && y0 - tmph < y1) {
            tmpHeight = y0 - y1;
        }
        else if (from_bottom == false && tmph + y0 > y2) {
            tmpHeight = y2 - y0;
        }
        else {
            tmpHeight = tmph;
        }
    }

    if (tmpWidth < 1 || tmpHeight < 1) {
        widget->resize(0, 0, 0, 0);
    }
    else if (from_right == true && from_bottom == true) {
        widget->resize(x0 - tmpWidth, y0 - tmpHeight, tmpWidth, tmpHeight);
    }
    else if (from_right == true && from_bottom == false) {
        widget->resize(x0 - tmpWidth, y0, tmpWidth, tmpHeight);
    }
    else if (from_right == false && from_bottom == true) {
        widget->resize(x0, y0 - tmpHeight, tmpWidth, tmpHeight);
    }
    else {
        widget->resize(x0, y0, tmpWidth, tmpHeight);
    }

    if (from_right == true) {
        x0 -= (tmpWidth + space);
    }
    else {
        x0 += (tmpWidth + space);
    }
}

/**
 * @brief Start a new layout placement of widgets from bottom left corner.
 *
 * @param border [in] Use border around widgets (1 font unit), default true.
 */
void Fl_Manual_Group::start_from_bottom_left(bool border) {
    font        = labelsize();
    space       = font / 2;
    x1          = border ? x() + font : x();
    y1          = border ? y() + font : y();
    x2          = border ? x() + w() - font : x() + w();
    y2          = border ? y() + h() - font : y() + h();
    x0          = x1;
    y0          = y2;
    from_right  = false;
    from_bottom = true;
}

/**
 * @brief Start a new layout placement of widgets from bottom right corner.
 *
 * @param border [in] Use border around widgets (1 font unit), default true.
 */
void Fl_Manual_Group::start_from_bottom_right(bool border) {
    font        = labelsize();
    space       = font / 2;
    x1          = border ? x() + font : x();
    y1          = border ? y() + font : y();
    x2          = border ? x() + w() - font : x() + w();
    y2          = border ? y() + h() - font : y() + h();
    x0          = x2;
    y0          = y2;
    from_right  = true;
    from_bottom = true;
}

/**
 * @brief Start a new layout placement of widgets from top left corner.
 *
 * @param border [in] Use border around widgets (1 font unit), default true.
 */
void Fl_Manual_Group::start_from_top_left(bool border) {
    font        = labelsize();
    space       = font / 2;
    x1          = border ? x() + font : x();
    y1          = border ? y() + font : y();
    x2          = border ? x() + w() - font : x() + w();
    y2          = border ? y() + h() - font : y() + h();
    x0          = x1;
    y0          = y1;
    from_right  = false;
    from_bottom = false;
}

/**
 * @brief Start a new layout placement of widgets from top right corner.
 *
 * @param border [in] Use border around widgets (1 font unit), default true.
 */
void Fl_Manual_Group::start_from_top_right(bool border) {
    font        = labelsize();
    space       = font / 2;
    x1          = border ? x() + font : x();
    y1          = border ? y() + font : y();
    x2          = border ? x() + w() - font : x() + w();
    y2          = border ? y() + h() - font : y() + h();
    x0          = x2;
    y0          = y1;
    from_right  = true;
    from_bottom = false;
}
