15.1.204. tablet_qt/lib/margins.h

/*
    Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
    Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

    This file is part of CamCOPS.

    CamCOPS 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 3 of the License, or
    (at your option) any later version.

    CamCOPS 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 CamCOPS. If not, see <https://www.gnu.org/licenses/>.
*/

/*
    OPTIONAL LGPL: Alternatively, this file may be used under the terms of the
    GNU Lesser General Public License version 3 as published by the Free
    Software Foundation. You should have received a copy of the GNU Lesser
    General Public License along with CamCOPS. If not, see
    <https://www.gnu.org/licenses/>.
*/

#pragma once
#include <QRect>
#include <QSize>
class QLayout;
class QWidget;


class Margins {
    // Generic margin structure, because QRect isn't quite right for this,
    // passing around lots of separate integers is awkward and prone to
    // mis-ordering [was that getContentsMargins(&left, &top, &right, &bottom)
    // or getContentsMargins(&left, &right, &top, &bottom)?], and QMargins
    // doesn't do any of the useful things relating to widgets, layouts, or
    // calculations that you might wish.

public:
    // Construct with zero margins
    Margins();

    // Construct with specified margins.
    Margins(int left, int top, int right, int bottom);
    Margins(int each_side);
    Margins(int left_right, int top_bottom);

    // Set the margins.
    void set(int left, int top, int right, int bottom);

    // Clear everything to zero.
    void clear();

    // Ensure that all margins are >=0.
    void rationalize();

    // Are the margins all zero?
    bool isZero() const;

    // Return components:
    inline int left() const { return m_left; }
    inline int top() const { return m_top; }
    inline int right() const { return m_right; }
    inline int bottom() const { return m_bottom; }

    // Set components, and call rationalize():
    void setLeft(int width);
    void setRight(int width);
    void setTop(int height);
    void setBottom(int height);

    // Low-level access that does not call rationalize():
    int& rleft();
    int& rright();
    int& rtop();
    int& rbottom();

    // Add to specific margins:
    void addLeft(int width);
    void addRight(int width);
    void addTop(int height);
    void addBottom(int height);

    // Return the total size/height/width:
    QSize totalSize() const;
    int totalHeight() const;
    int totalWidth() const;

    // Adds the sum of our left/right margins to "width".
    int addLeftRightMarginsTo(int width) const;

    // Subtracts the sum of our left/right margins from  "width".
    int removeLeftRightMarginsFrom(int width) const;

    // Adds the sum of our top/bottom margins to "width".
    int addTopBottomMarginsTo(int height) const;

    // Subtracts the sum of our top/bottom margins from "width".
    int removeTopBottomMarginsFrom(int height) const;

    // Add our stored margins to a variety of objects:
    QSize addMarginsTo(const QSize& size) const;
    QRect addMarginsTo(const QRect& rect) const;
    void addMarginsToInPlace(QSize& size) const;
    void addMarginsToInPlace(QRect& rect) const;
    void addMarginsToInPlace(Margins& other) const;

    // Adjust a QRect by our top/left margins:
    QRect moveRectByTopLeftMargins(const QRect& rect) const;
    void moveRectByTopLeftMarginsInPlace(QRect& rect) const;

    // Remove our stored margins from a variety of objects:
    QSize removeMarginsFrom(const QSize& size) const;
    QRect removeMarginsFrom(const QRect& rect) const;
    void removeMarginsFromInPlace(QRect& rect) const;

    // Return the getContentsMargins() of a QWidget.
    static Margins getContentsMargins(const QWidget* widget);

    // Return the getContentsMargins() of a QLayout.
    static Margins getContentsMargins(const QLayout* layout);

    // Returns the margins by which "outer" is larger than "inner".
    // The results may be nonsensical if "outer" does not contain "inner".
    static Margins rectDiff(const QRect& outer, const QRect& inner);

    // Here we suppose that "inner" is a rectangle defined relative to (0,0)
    // of a rectangle with size "outer". (Prototypically: a widget with
    // geometry outer has a sub-widget, RELATIVE TO IT, with geometry inner.)
    // Returns the margins that would have to be applied to "inner" to make it
    // reach "outer".
    static Margins subRectMargins(const QSize& outer, const QRect& inner);

    // Returns subRectMargins(outer.size(), inner).
    static Margins subRectMargins(const QRect& outer, const QRect& inner);

private:
    int m_left;  // left margin
    int m_top;  // top margin
    int m_right;  // right margin
    int m_bottom;  // bottom margin

public:
    // Debugging description.
    friend QDebug operator<<(QDebug debug, const Margins& m);
};