#include <list>
#include <set>
#include <sigc++/trackable.h>
+#include <msp/strings/lexicalcast.h>
#include "geometry.h"
+#include "mspgltk_api.h"
namespace Msp {
namespace GLtk {
+class Arrangement;
class Container;
class Widget;
dependent widgets have the expand flag set, the results are currently
undefined.
-Since specifiyng constraints manually can be quite tedious, there are some
-derived Layout classes that implement common positioning patterns. See Row,
-Column, MixedRows and Grid.
+Since specifiyng constraints manually can be quite tedious, an Arrangement
+interface is provided to automatically arrange widgets. See classes Row,
+Column and Grid for some commonly used arrangements.
*/
-class Layout
+class MSPGLTK_API Layout
{
private:
enum
VERTICAL = 1,
SELF_POS = 2,
SELF_DIM = 4,
+ SELF_MASK = 6,
TARGET_POS = 8,
TARGET_DIM = 16,
- SPACING = 32
+ TARGET_MASK = 24,
+ HALF_DIM = 32,
+ SPACING = 64,
+ SLACK = 128
};
public:
BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
+ FAR_ABOVE = VERTICAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING|SLACK,
+ FAR_BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING|SLACK,
+ FAR_RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING|SLACK,
+ FAR_LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING|SLACK,
ALIGN_TOP = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
+ ALIGN_VCENTER = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM|HALF_DIM,
ALIGN_BOTTOM = VERTICAL|SELF_POS|TARGET_POS,
ALIGN_RIGHT = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
+ ALIGN_HCENTER = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM|HALF_DIM,
ALIGN_LEFT = HORIZONTAL|SELF_POS|TARGET_POS,
COPY_WIDTH = HORIZONTAL|SELF_DIM|TARGET_DIM,
COPY_HEIGHT = VERTICAL|SELF_DIM|TARGET_DIM
};
-protected:
+ class Loader: public DataFile::ObjectLoader<Layout>
+ {
+ public:
+ typedef std::map<std::string, Widget *> WidgetMap;
+
+ private:
+ const WidgetMap &wdg_map;
+
+ public:
+ Loader(Layout &, const WidgetMap &);
+
+ private:
+ void column_spacing(unsigned);
+ void margin();
+ void row_spacing(unsigned);
+ void spacing(unsigned);
+ void widget(const std::string &);
+ };
+
+private:
+ class WidgetLoader: public DataFile::Loader
+ {
+ private:
+ Layout &layout;
+ Widget &widget;
+ const Layout::Loader::WidgetMap &wdg_map;
+
+ public:
+ WidgetLoader(Layout &, Widget &, const Layout::Loader::WidgetMap &);
+
+ private:
+ void constraint(ConstraintType, const std::string &);
+ void expand(bool, bool);
+ void ghost(bool);
+ void gravity(int, int);
+ };
+
struct Slot;
struct Constraint
{
ConstraintType type;
Slot ⌖
+ int spacing = -1;
Constraint(ConstraintType, Slot &);
};
struct Packing
{
- int gravity;
- bool expand;
-
- Packing();
+ int gravity = -1;
+ bool expand = false;
};
struct Slot: public sigc::trackable
{
Layout &layout;
- unsigned index;
+ int index = 0;
Widget &widget;
+ Geometry autosize_geom;
Geometry geom;
std::list<Constraint> constraints;
Packing horiz_pack;
Packing vert_pack;
+ bool ghost = false;
+ bool floating = false;
Slot(Layout &, Widget &);
- virtual ~Slot() { }
void autosize_changed();
+ void visibility_changed(bool);
+ };
+
+ enum SolveMode
+ {
+ UPDATE,
+ AUTOSIZE
};
class LinearProgram;
struct Pointers;
- Container *container;
+ Container *container = nullptr;
std::list<Slot *> slots;
- Sides margin;
- unsigned row_spacing;
- unsigned col_spacing;
+ unsigned n_active_slots = 0;
+ unsigned n_slack_vars[2] = { 0, 0 };
+ Sides margin{ 8 };
+ unsigned row_spacing = 5;
+ unsigned col_spacing = 4;
+ Geometry autosize_geom;
+ std::list<Arrangement *> arrangement_stack;
static Pointers pointers[2];
public:
- Layout();
- virtual ~Layout();
+ ~Layout();
void set_container(Container &);
void set_margin(const Sides &);
+ const Sides &get_margin() const { return margin; }
+
+ /** Sets the default spacing between widgets in both directions. */
void set_spacing(unsigned);
+
+ /** Sets the default vertical spacing between widgets. Affects the ABOVE
+ and BELOW constraints. */
void set_row_spacing(unsigned);
+
+ /** Sets the default horizontal spacing between widgets. Affects the
+ LEFT_OF and RIGHT_OF constraints. */
void set_column_spacing(unsigned);
+ unsigned get_row_spacing() const { return row_spacing; }
+ unsigned get_column_spacing() const { return col_spacing; }
+
+ void push_arrangement(Arrangement &);
+ Arrangement *get_arrangement() const;
+ void pop_arrangement(Arrangement &);
+
void add_widget(Widget &);
void remove_widget(Widget &);
-protected:
- virtual Slot *create_slot(Widget &);
+private:
+ void update_slot_indices();
Slot &get_slot_for_widget(Widget &);
static ConstraintType complement(ConstraintType);
+ void create_constraint(Widget &, ConstraintType, Widget &, int);
+
public:
- void add_constraint(Widget &, ConstraintType, Widget &);
+ /** Adds a constraint between two widgets. */
+ void add_constraint(Widget &src, ConstraintType type, Widget &tgt);
+
+ /** Adds a constraint between two widgets, overriding the default spacing.
+ Not all constraint types use a spacing. */
+ void add_constraint(Widget &src, ConstraintType type, Widget &tgt, unsigned);
+
void set_gravity(Widget &, int, int);
void set_expand(Widget &, bool, bool);
+ /// Sets a widget as a ghost, taking up space even if it is hidden.
+ void set_ghost(Widget &, bool);
+
+ void set_floating(Widget &, bool);
+
void update();
+ void autosize(Geometry &);
-protected:
- void find_constraint_group(Slot &, ConstraintType, std::set<Slot *> &);
- void sort_slots(std::list<Slot *> &, ConstraintType);
- void solve_constraints(int);
+private:
+ void solve_constraints(int, SolveMode);
};
+MSPGLTK_API void operator>>(const LexicalConverter &, Layout::ConstraintType &);
+
} // namespace GLtk
} // namespace Msp