]> git.tdb.fi Git - libs/gltk.git/blobdiff - source/layout.h
Better method of implementing zero gravity
[libs/gltk.git] / source / layout.h
index 7e8cdea123fc1a25f845bfb5ecf3e272df9d9b57..043d92cc1554b738092ce3ad771fcf5bb3cc5049 100644 (file)
@@ -1,21 +1,16 @@
-/* $Id$
-
-This file is part of libmspgltk
-Copyright © 2011  Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
 #ifndef MSP_GLTK_LAYOUT_H_
 #define MSP_GLTK_LAYOUT_H_
 
 #include <list>
 #include <set>
 #include <sigc++/trackable.h>
+#include <msp/strings/lexicalcast.h>
 #include "geometry.h"
 
 namespace Msp {
 namespace GLtk {
 
+class Arrangement;
 class Container;
 class Widget;
 
@@ -27,11 +22,11 @@ is then solved to obtain positions and dimensions that fulfill the constraints.
 There are three kinds of constraints available: ordering, alignment and
 dimension matching.
 
-Ordering constraints specify that the widgets should be placed next to other
-along X or Y axis.  These operate on one axis at a time, so a widget could be
-"right of" another even if they are separated by hundreds of pixels vertically.
-The widgets will be separated by a spacing value, which is settable on a per-
-layout basis.
+Ordering constraints specify that the widgets should be placed next to each
+other along X or Y axis.  These operate on one axis at a time, so a widget
+could be "right of" another even if they are separated by hundreds of pixels
+vertically.  The widgets will be separated by a spacing value, which is
+settable on a per-layout basis.
 
 Alignment constraints make the corresponding edges of two widgets be on the
 same line.  These are incompatible with ordering constraints, so only one or
@@ -51,9 +46,9 @@ flag for a widget causes it to use as much space as possible.  If multiple co-
 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
-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
 {
@@ -64,9 +59,12 @@ private:
                VERTICAL = 1,
                SELF_POS = 2,
                SELF_DIM = 4,
+               SELF_MASK = 6,
                TARGET_POS = 8,
                TARGET_DIM = 16,
-               SPACING = 32
+               TARGET_MASK = 24,
+               SPACING = 32,
+               SLACK = 64
        };
 
 public:
@@ -76,6 +74,10 @@ 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_BOTTOM = VERTICAL|SELF_POS|TARGET_POS,
                ALIGN_RIGHT = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
@@ -84,13 +86,50 @@ public:
                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 &target;
+               int spacing;
 
                Constraint(ConstraintType, Slot &);
        };
@@ -106,17 +145,25 @@ protected:
        struct Slot: public sigc::trackable
        {
                Layout &layout;
-               unsigned index;
+               int index;
                Widget &widget;
+               Geometry autosize_geom;
                Geometry geom;
                std::list<Constraint> constraints;
                Packing horiz_pack;
                Packing vert_pack;
+               bool ghost;
 
                Slot(Layout &, Widget &);
-               virtual ~Slot() { }
 
                void autosize_changed();
+               void visibility_changed(bool);
+       };
+
+       enum SolveMode
+       {
+               UPDATE,
+               AUTOSIZE
        };
 
        class LinearProgram;
@@ -124,41 +171,73 @@ protected:
 
        Container *container;
        std::list<Slot *> slots;
+       unsigned n_active_slots;
+       unsigned n_slack_vars[2];
        Sides margin;
        unsigned row_spacing;
        unsigned col_spacing;
+       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 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);
 };
 
+void operator>>(const LexicalConverter &, Layout::ConstraintType &);
+
 } // namespace GLtk
 } // namespace Msp