ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/include/ndk/packer.hh
Revision: 1.1
Committed: Sun Oct 24 20:31:43 2010 UTC (15 years, 11 months ago) by sf-pippijn
Branch: MAIN
CVS Tags: HEAD
Log Message:
use EV and plain sockets instead of asio

File Contents

# User Rev Content
1 sf-pippijn 1.1 /* packer.hh
2     * This file is part of ndk library
3     * Copyright (c) 2003,2004 by Stanislav Ievlev
4     *
5     * This file is covered by the GNU Library General Public License,
6     * which should be included with libndk as the file COPYING.
7     */
8     #ifndef NDK_PACKER_HH__
9     #define NDK_PACKER_HH__
10    
11     #include <algorithm>
12     #include <functional>
13     #include <vector>
14    
15     #include <ndk/align.hh>
16     #include <ndk/panel.hh>
17     #include <ndk/support.hh>
18    
19     namespace ndk
20     {
21     namespace pack /**< packer strategies */
22     {
23     struct vertical /**< vertical packing strategy */
24     {
25     static int align_coord (panel *p)
26     {
27     return p->x ();
28     }
29    
30     static int align_size (panel *p)
31     {
32     return p->width ();
33     }
34    
35     static void align_move (panel *p, int pos)
36     {
37     p->move (pos, p->y (), absolute);
38     }
39    
40     static void align_resize (panel *p, int size)
41     {
42     const bool need_update = (p->width () != size);
43    
44     p->resize (size, p->height ());
45     if (need_update)
46     p->draw ();
47     }
48    
49     static int line_coord (panel *p)
50     {
51     return p->y ();
52     }
53    
54     static int line_size (panel *p)
55     {
56     return p->height ();
57     }
58    
59     static void line_move (panel *p, int pos)
60     {
61     p->move (p->x (), pos, absolute);
62     }
63    
64     static void resize (panel *p, int align_size, int line_size)
65     {
66     p->resize (align_size, line_size);
67     }
68     };
69    
70     struct horizontal /**< horizontal packing strategy */
71     {
72     static int align_coord (panel *p)
73     {
74     return p->y ();
75     }
76    
77     static int align_size (panel *p)
78     {
79     return p->height ();
80     }
81    
82     static void align_move (panel *p, int pos)
83     {
84     p->move (p->x (), pos, absolute);
85     }
86    
87     static void align_resize (panel *p, int size)
88     {
89     const bool need_update = (p->height () != size);
90    
91     p->resize (p->width (), size);
92     if (need_update)
93     p->draw ();
94     }
95    
96     static int line_coord (panel *p)
97     {
98     return p->x ();
99     }
100    
101     static int line_size (panel *p)
102     {
103     return p->width ();
104     }
105    
106     static void line_move (panel *p, int pos)
107     {
108     p->move (pos, p->y (), absolute);
109     }
110    
111     static void resize (panel *p, int align_size, int line_size)
112     {
113     p->resize (line_size, align_size);
114     }
115     };
116    
117     template<class T>
118     struct def_resizer /**< default resize policy for the packer object */
119     {
120     static void fix_item (panel *p, int, int pos)
121     {
122     T::align_move (p, pos);
123     }
124    
125     static void fix_panel (panel *p, int align_size, int line_size)
126     {
127     T::resize (p, align_size, line_size);
128     }
129    
130     static void draw (panel *p)
131     {
132     p->draw ();
133     }
134     };
135    
136     template<class T>
137     struct no_resizer /**< * this policy don't made resize of the object */
138     {
139     static void fix_item (panel *p, int size, int pos)
140     {
141     T::align_move (p, pos);
142     T::align_resize (p, size);
143     }
144    
145     static void fix_panel (panel *, int, int)
146     {
147     }
148    
149     static void draw (panel *)
150     {
151     }
152     };
153     }
154    
155     template<class T>
156     bool
157     wider_panel (panel *p1, panel *p2)
158     {
159     /**< compare panels, who is wider */
160     return T::align_size (p1) < T::align_size (p2);
161     }
162    
163     /**
164     * general template to the auto packer/aligner of widgets
165     * packer algorithm:
166     * with resizer:
167     * 1. find widget with maximum size (max)
168     * 2. main widget size is max + 2*padding
169     * 3. align all widgets and place it with begining from padding
170     * 4. resize main to size max + 2*padding, and total widgets length+2*padding
171     * without resizer:
172     * 1. find widget with maximum size
173     * 2. align all widgets, according max widget size and with begining from padding
174     * 3. resize all widgets to the "main - 2*padding" if we need it
175     */
176     template<class T, template<class> class resizer = pack::def_resizer>
177     class packer
178     {
179     typedef std::vector<panel *> widget_vector;
180     typedef resizer<T> resizer_type;
181    
182     public:
183     packer (panel *main, align::type alignment, int padding = 0)
184     : main_ (main)
185     , padding_ (padding)
186     , align_ (alignment)
187     {
188     }
189    
190     void add (panel *item)
191     {
192     widgets_.push_back (item);
193     resizer_type::draw (item); /* in auto resize method we need to draw widgets to know it's real sizes */
194     }
195    
196     void pack () /**< move and align widgets */
197     {
198     if (widgets_.empty ())
199     return;
200    
201     /* first made alignment */
202     widget_vector::const_iterator max_item =
203     std::max_element (widgets_.begin (), widgets_.end (), wider_panel<T> );
204     const int align_size = T::align_size (*max_item) + main_->padding () * 2;
205     foreach (panel *widget, widgets_)
206     do_align (widget, T::align_size (*max_item));
207    
208     int pos = main_->padding ();
209     foreach (panel *widget, widgets_)
210     do_move (widget, pos);
211     const int line_size = pos - padding_ + main_->padding ();
212    
213     resizer_type::fix_panel (main_, align_size, line_size); /* try to fix size of the panel */
214     }
215    
216     private:
217     void do_align (panel *p, int max) /**< align panel's possition according current aligment */
218     {
219     resizer_type::fix_item (p, T::align_size (main_) - 2 * main_->padding (),
220     T::align_coord (main_) +
221     main_->padding () +
222     align::pos (T::align_size (p), max, align_));
223     }
224    
225     void do_move (panel *p, int &pos) /**< move next item according current packing */
226     {
227     T::line_move (p, T::line_coord (main_) + pos);
228     pos += T::line_size (p) + padding_;
229     }
230    
231     widget_vector widgets_; /**< widgets to pack */
232     panel *main_; /**< main widget, we will try to place all widgets under it*/
233     int padding_; /**< size of empty area between widgets on the line */
234     align::type align_; /**< aligment of the widgets */
235     };
236    
237     typedef packer<pack::horizontal> horizontal_packer;
238     typedef packer<pack::vertical> vertical_packer;
239     }
240    
241     #endif