1 //------------------------------------------------------------------------------
2 // emPackLayout.h
3 //
4 // Copyright (C) 2015 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20
21 #ifndef emPackLayout_h
22 #define emPackLayout_h
23
24 #ifndef emBorder_h
25 #include <emCore/emBorder.h>
26 #endif
27
28
29 //==============================================================================
30 //================================ emPackLayout ================================
31 //==============================================================================
32
33 class emPackLayout : public emBorder {
34
35 public:
36
37 // A panel of this class automatically lays out its child panels within
38 // the content area by a special "pack" algorithm, which allows to give
39 // each child panel a weight (area proportion) and a preferred tallness
40 // (height/width ratio). This should be used only for up to about seven
41 // child panels. With more, the algorithm may not find an optimal
42 // layout.
43 //
44 // Pack layout
45 // +---------------------------------------------+
46 // | +------------------+ +---------+ +-----+ |
47 // | | | | | | | |
48 // | | | | | | | |
49 // | | | | | | | |
50 // | | | | | +-----+ |
51 // | | | | | |
52 // | | | | | +-----+ |
53 // | | | | | | | |
54 // | +------------------+ | | | | |
55 // | | | | | |
56 // | +------------------+ | | | | |
57 // | | | | | | | |
58 // | | | | | | | |
59 // | +------------------+ +---------+ +-----+ |
60 // +---------------------------------------------+
61 //
62 // The algorithm recursively divides the available area and the child
63 // panel set into two areas and two child panel sets until each area has
64 // only one panel. Thereby, the order of child panels is kept. The area
65 // proportions are calculated from the given weights. The decision where
66 // (at which child panel) and how (horizontally or vertically) the
67 // dividing in each recursive step is made, is determined by iterating
68 // multiple possibilities until a solution is found which satisfies the
69 // preferred tallnesses best possible. Because this would be too time
70 // consuming for large sets, the algorithm reduces the number of
71 // iterations in a recursive step depending on the size of the set (down
72 // to zero for large sets). This way, an optimum is guaranteed only for
73 // up to seven child panels.
74 //
75 // By default, a panel of this class is not focusable and has no border,
76 // because it is meant as a pure layout programming tool. For other use,
77 // please see the derived class emPackGroup.
78
79 emPackLayout(
80 ParentArg parent, const emString & name,
81 const emString & caption=emString(),
82 const emString & description=emString(),
83 const emImage & icon=emImage()
84 );
85 // Like emBorder, but sets non-focusable.
86
87 virtual ~emPackLayout();
88 // Destructor.
89
90 int GetMinCellCount() const;
91 void SetMinCellCount(int minCellCount);
92 // Minimum number of cells to be generated. The layout algorithm
93 // behaves like if there were at least this number of child
94 // panels. The additional cells are simply making up unused
95 // space. The default is zero.
96
97 double GetChildWeight(int index) const;
98 void SetChildWeight(int index, double weight);
99 // Get or set the weight of a child panel. The bigger the weight
100 // of a child panel, the bigger is the proportion of the
101 // available area given to that panel by the layout algorithm.
102 // It is a simple linear relation. The index argument denotes a
103 // child panel. Zero means first child, one means second, and so
104 // on. The default weight is 1.0.
105
106 void SetChildWeight(double weight);
107 // Set the weight of all child panels to the given value.
108
109 double GetPrefChildTallness(int index) const;
110 void SetPrefChildTallness(int index, double pct);
111 // Get or set the preferred tallness (height/width ratio) of a
112 // child panel. The index argument denotes a child panel. Zero
113 // means first child, one means second, and so on. The default
114 // preferred tallness is 0.2.
115
116 void SetPrefChildTallness(double pct);
117 // Set the preferred tallness of all child panels to the given
118 // value.
119
120 protected:
121
122 virtual void LayoutChildren();
123 // Lays out all child panels in the content area (except for an
124 // auxiliary panel, which is laid out in the border).
125
126 private:
127
128 struct TmpPanelInfo {
129 double PCT;
130 double CumulativeWeight;
131 double CumulativeLogPCT;
132 emPanel * Panel;
133 };
134
135 struct TmpInfo {
136 TmpPanelInfo * TPIs;
137 emColor CanvasColor;
138 };
139
140 int CountCells();
141 void FillTPIs(int count);
142 double GetTPIWeightSum(int index, int count) const;
143 double GetTPILogPCTSum(int index, int count) const;
144
145 double RateCell(int index, double w, double h);
146
147 double Pack1(
148 int index,
149 double x, double y, double w, double h,
150 bool execute
151 );
152
153 double Pack2(
154 int index,
155 double x, double y, double w, double h,
156 double bestError, bool execute
157 );
158
159 double Pack3(
160 int index,
161 double x, double y, double w, double h,
162 double bestError, bool execute
163 );
164
165 double PackN(
166 int index, int count,
167 double x, double y, double w, double h,
168 double bestError, bool execute
169 );
170
171 double RateHorizontally(
172 int index, int count, int div,
173 double x, double y, double w1, double w2, double h,
174 double bestError
175 );
176
177 double RateVertically(
178 int index, int count, int div,
179 double x, double y, double w, double h1, double h2,
180 double bestError
181 );
182
183 double DefaultWeight;
184 double DefaultPCT;
185 emArray<double> WeightArray;
186 emArray<double> PCTArray;
187 int MinCellCount;
188 TmpInfo * TI;
189 int Ratings;
190 };
191
192
GetMinCellCount()193 inline int emPackLayout::GetMinCellCount() const
194 {
195 return MinCellCount;
196 }
197
198
199 #endif
200