Better error message in flexible.inc
[project/panels.git] / layouts / flexible / flexible.inc
CommitLineData
f2e5a0c5
EM
1<?php
2// $Id$
3
f2e5a0c5 4/**
fc8f8fa8 5 * Implementation of hook_panels_layouts()
f2e5a0c5
EM
6 */
7function panels_flexible_panels_layouts() {
8 $items['flexible'] = array(
9 'title' => t('Flexible'),
fc8f8fa8 10 'icon' => 'flexible.png',
f2e5a0c5 11 'theme' => 'panels_flexible',
fc8f8fa8 12 'css' => 'flexible.css',
f2e5a0c5
EM
13 'settings form' => 'panels_flexible_settings_form',
14 'settings submit' => 'panels_flexible_settings_submit',
2edbdf2c 15 'settings validate' => 'panels_flexible_settings_validate',
f2e5a0c5
EM
16 'panels function' => 'panels_flexible_panels',
17 );
18
19 return $items;
20}
21
22function panels_flexible_default_panels() {
23 return array(
24 'percent_width' => 100,
25 'rows' => 3,
26 'width_type' => '%',
27 'row_1' => array(
28 'columns' => 1,
29 'width_1' => 100,
30 'names' => array(t('Top')),
31 ),
32 'row_2' => array(
33 'columns' => 3,
34 'width_1' => 25,
35 'width_2' => 50,
36 'width_3' => 25,
37 'names' => array(t('Left'), t('Middle'), t('Right')),
38 ),
39 // row 3
40 'row_3' => array(
41 'columns' => 1,
42 'width_1' => 100,
43 'names' => array(t('Bottom')),
44 ),
45 'sidebars' => array(
46 'left' => FALSE,
47 'left_width' => 200,
48 'right' => FALSE,
49 'right_width' => 200,
50 'width_type' => 'px',
51 ),
52 );
53}
54
55function panels_flexible_settings_form($display, $layout, $settings) {
56 if (empty($settings)) {
57 // default for a new flexible layout
58 $settings = panels_flexible_default_panels();
59 }
60
61 // Special check for updating:
62 if (empty($settings['width_type'])) {
63 $settings['width_type'] = '%';
64 $settings['percent_width'] = 100;
65 $settings['sidebars']['left'] = FALSE;
66 $settings['sidebars']['left_width'] = 200;
67 $settings['sidebars']['right'] = FALSE;
68 $settings['sidebars']['right_width'] = 200;
69 $settings['sidebars']['width_type'] = 'px';
70 }
71
72 $form['instructions'] = array(
73 '#value' => t('<p>Here you may determine the number of rows and columns your layout may have. Each row can have its own number of columns, and each column can have its width set independently. When changing the number of rows or columns, click Save to update the form so you can set the widths for new cells properly.</p><p><strong>Note: Removing cells which contain panes will cause those panes to be disappear. Please move any content you wish to keep.</strong></p>'),
74 );
75
76 $form['width_type'] = array(
77 '#type' => 'select',
78 '#title' => t('Width unit type'),
79 '#options' => array('%' => t('% (percentage)'), 'px' => t('px (pixels)'), 'em' => t('em (current)')),
80 '#description' => t('The width unit type this layout can have: %, px or em. When using percentage, your layout will be fluid; when using px or em, your layout will be fixed.'),
81 '#default_value' => $settings['width_type'],
82 );
83
84 $form['percent_width'] = array(
85 '#type' => 'textfield',
86 '#size' => 2,
87 '#width' => 10,
88 '#title' => t('Total width'),
89 '#description' => t('If using the percentage width, choose the total width that this layout must add up to; if you are having problems with your flexible layout having columns fall off, try lowering this number and adjusting the width of individual columns to match.'),
90 '#default_value' => $settings['percent_width'],
91 );
92
93 $form['rows'] = array(
94 '#type' => 'textfield',
95 '#size' => 2,
96 '#width' => 10,
97 '#title' => t('Rows'),
98 '#description' => t('The number of rows this layout can have.'),
99 '#default_value' => $settings['rows'],
100 );
101
102 for ($row = 1; $row <= intval($settings['rows']); $row++) {
103 $form["row_$row"] = array(
104 '#type' => 'fieldset',
105 '#title' => t('Row @d', array('@d' => $row)),
106 );
107 $form["row_$row"]["columns"] = array(
108 '#prefix' => '<div style="float: left; padding-right: 2em">',
109 '#suffix' => '</div>',
110 '#type' => 'textfield',
111 '#size' => 2,
112 '#width' => 10,
113 '#title' => t('Columns'),
114// '#description' => t('The number of columns in row @d.', array('@d' => $row)),
115 '#default_value' => $settings["row_$row"]["columns"],
116 );
117 for ($col = 1; $col <= intval($settings["row_$row"]["columns"]); $col++) {
6c09ec8c 118 $form["row_$row"]["width_$col"] = array(
f2e5a0c5
EM
119 '#prefix' => '<div style="float: left; padding-right: 2em">',
120 '#suffix' => '</div>',
121 '#type' => 'textfield',
122 '#size' => 2,
123 '#width' => 10,
124 '#title' => t('Width @d', array('@d' => $col)),
125 '#default_value' => $settings["row_$row"]["width_$col"],
126 );
127 }
128 if (is_array($settings["row_$row"]["names"])) {
129 $names = implode(', ', $settings["row_$row"]["names"]);
130 }
131 else {
132 $names = '';
133 }
134 $form["row_$row"]['names'] = array(
135 '#prefix' => '<div style="float: left;">',
136 '#suffix' => '</div>',
137 '#type' => 'textfield',
138 '#title' => t('Column titles, separated by commas'),
139 '#default_value' => $names,
140 );
141 }
142
143 $form['sidebars'] = array(
144 '#type' => 'fieldset',
145 '#title' => t('Sidebars'),
146 );
147
148 $form['sidebars']['left_aligner_start'] = array(
149 '#value' => '<div class="option-text-aligner">',
150 '#tree' => TRUE,
151 );
152 $form['sidebars']['left'] = array(
153 '#type' => 'checkbox',
154 '#id' => 'sidebar-left-checkbox',
155 '#title' => t('Sidebar left'),
156 '#default_value' => $settings['sidebars']['left'],
157 );
158 $form['sidebars']['left_width'] = array(
159 '#type' => 'textfield',
160 '#id' => 'sidebar-left-width',
161 '#size' => 2,
162 '#width' => 10,
163 '#default_value' => $settings['sidebars']['left_width'],
164 );
165 $form['sidebars']['right'] = array(
166 '#type' => 'checkbox',
167 '#id' => 'sidebar-right-checkbox',
168 '#title' => t('Sidebar right'),
169 '#default_value' => $settings['sidebars']['right'],
170 );
171
172 $form['sidebars']['right_width'] = array(
173 '#type' => 'textfield',
174 '#id' => 'sidebar-right-width',
175 '#size' => 2,
176 '#width' => 10,
177 '#default_value' => $settings['sidebars']['right_width'],
178 );
179 $form['sidebars']['left_aligner_stop'] = array(
180 '#value' => '</div><div style="clear: both; padding: 0; margin: 0"></div>',
181 );
182 $form['sidebars']['left_title_markup'] = array(
183 '#prefix' => '<div class="description">',
184 '#suffix' => '</div>',
185 '#value' => t('If a sidebar is selected, enter the width of the sidebar.'),
186 );
187
188 $form['sidebars']['width_type'] = array(
189 '#type' => 'select',
190 '#title' => t('Width unit type'),
191 '#options' => array('%' => t('% (percentage)'), 'px' => t('px (pixels)'), 'em' => t('em (current)')),
192 '#description' => t('The width unit type activated sidebars will have: %, px or em. When using percentage, your sidebars will be fluid; when using px or em, your sidebars will be fixed.'),
193 '#default_value' => $settings['sidebars']['width_type'],
194 );
195
196 $js_settings = array('panels' => array('checkboxes' => array(
197 '#sidebar-left-checkbox' => array('#sidebar-left-width'),
198 '#sidebar-right-checkbox' => array('#sidebar-right-width'),
199 )));
6c09ec8c
EM
200 // not needed, automatically happens on the layout settings page.
201// drupal_add_js(panels_get_path('js/checkboxes.js'));
f2e5a0c5
EM
202 drupal_add_js($js_settings, 'setting');
203 return $form;
204}
205
206function panels_flexible_settings_validate($values, $form, $display, $layout, $settings) {
6c09ec8c
EM
207 if (empty($settings)) {
208 $settings = panels_flexible_default_panels();
209 }
210
f2e5a0c5
EM
211 if ($values['rows'] < 1) {
212 form_error($form['rows'], t('Rows must be a positive integer.'));
213 return;
214 }
215
216 // Validate that percentages add up to the stated maximum.
dd58fceb 217 if ($values['width_type'] == '%') {
f2e5a0c5
EM
218 for ($row = 1; $row <= intval($values['rows']); $row++) {
219 // This takes into account whether or even had a previous setting here.
220 if ($settings['rows'] >= $row) {
221 if ($values["row_$row"]['columns'] < 1) {
222 form_error($form["row_$row"]['columns'], t('Columns must be a positive integer.'));
223 return;
224 }
225 $total = 0;
226 for ($col = 1; $col <= intval($values["row_$row"]["columns"]); $col++) {
227 $total += $values["row_$row"]["width_$col"];
228 }
7ac7b2cb
EM
229 if ($total != $values['percent_width']) {
230 form_error($form["row_$row"]['columns'], t('Column widths must add up to @count.', array('@count' => $values['percent_width'])));
f2e5a0c5
EM
231 }
232 }
233 }
234 }
235}
236
237function panels_flexible_settings_submit(&$values, $display, $layout, $settings) {
6c09ec8c
EM
238 if (empty($settings)) {
239 $settings = panels_flexible_default_panels();
240 }
241
f2e5a0c5
EM
242 for ($row = 1; $row <= $values['rows']; $row++) {
243 if ($row > $settings['rows'] && empty($values["row_$row"]['columns'])) {
244 $values["row_$row"]['columns'] = 1;
245 $values["row_$row"]['width_1'] = 100;
246 }
247 if (!empty($values["row_$row"]['names'])) {
248 $names = explode(',', $values["row_$row"]['names']);
249 foreach ($names as $nid => $name) {
250 $names[$nid] = trim($name);
251 }
252 $values["row_$row"]['names'] = $names;
253 }
254 }
255}
256
257/**
258 * Define the actual list of columns and rows for this flexible panel.
259 */
260function panels_flexible_panels($display, $settings) {
261 $panels = array();
262 if (empty($settings)) {
263 $settings = panels_flexible_default_panels();
264 }
265
266 if (!empty($settings['sidebars']['left'])) {
267 $panels['sidebar_left'] = t('Left sidebar');
268 }
269
270 if (!empty($settings['sidebars']['right'])) {
271 $panels['sidebar_right'] = t('Right sidebar');
272 }
273
274 for ($row = 1; $row <= intval($settings['rows']); $row++) {
275 for ($col = 1; $col <= intval($settings["row_$row"]['columns']); $col++) {
276 if (!empty($settings["row_$row"]['names'][$col - 1])) {
277 $panels["row_${row}_$col"] = $settings["row_$row"]['names'][$col - 1];
278 }
279 else {
280 $panels["row_${row}_$col"] = t("Row @row, Column @col", array('@row' => $row, '@col' => $col));
281 }
282 }
283 }
284 return $panels;
285}
286
287/**
288 * This function uses heredoc notation to make it easier to convert
289 * to a template.
290 */
291function theme_panels_flexible($id, $content, $settings) {
292 if (empty($settings)) {
293 $settings = panels_flexible_default_panels();
294 }
295
296 // Special check for updating.
297 if (empty($settings['width_type'])) {
298 $settings['width_type'] = '%';
299 $settings['percent_width'] = 100;
300 }
301
302 if ($id) {
303 $idstr = " id='$id'";
304 $idcss = "#$id";
305 }
306 else {
6c09ec8c 307 $idstr = '';
f2e5a0c5
EM
308 $idcss = "div.panel-flexible";
309 }
310
311 $css = '';
312 $output = '';
313
314 for ($row = 1; $row <= intval($settings['rows']); $row++) {
315 $output .= "<div class=\"panel-row panel-row-$row clear-block\">\n";
316 for ($col = 1; $col <= intval($settings["row_$row"]["columns"]); $col++) {
317 // We do a width reduction formula to help IE out a little bit. If width is 100%, we take 1%
318 // off the total; by dividing by the # of columns, that gets us the reduction overall.
319 $reduce = 0;
320 if ($settings['width_type'] == '%' && $settings['percent_width'] == 100) {
321 $reduce = 1 / $settings["row_$row"]["columns"];
322 }
323 if ($col == 1) {
324 if (intval($settings["row_$row"]["columns"]) == 1) {
325 $class = 'panel-col-only';
326 }
327 else {
328 $class = 'panel-col-first';
329 }
330 }
331 elseif ($col == intval($settings["row_$row"]["columns"])) {
332 $class = 'panel-col-last';
333 }
334 else {
335 $class = 'panel-col-inside';
336 }
337 $output .= "<div class=\"panel-col panel-col-$col $class\">\n";
338 $output .= "<div class=\"inside\">" . $content["row_${row}_$col"] . "</div>\n";
339 $output .= "</div>\n"; // panel-col-$col
340 $css .= "$idcss div.panel-row-$row div.panel-col-$col { width: " . ((intval($settings["row_$row"]["width_$col"])) - $reduce) . $settings["width_type"] ."; }\n";
341 }
342 $output .= "</div>\n"; // panel-row-$row
343 }
344
345 // Add our potential sidebars
346 if (!empty($settings['sidebars']['left']) || !empty($settings['sidebars']['right'])) {
347 // provide a wrapper if we have a sidebar
348 $output = "<div class=\"panel-sidebar-middle panel-sidebar\">\n$output</div>\n";
349 if ($settings['sidebars']['width_type'] == '%') {
350 $css .= "$idcss div.panel-flexible-sidebars div.panel-sidebar-middle { width: " . (intval($settings['percent_width']) - intval($settings['sidebars']['left_width']) - intval($settings['sidebars']['right_width'])) . "; }\n";
351 }
352 }
353
354 if (!empty($settings['sidebars']['left'])) {
355 $size = intval($settings['sidebars']['left_width']) . $settings['sidebars']['width_type'];
356 $output = "<div class=\"panel-sidebar panel-sidebar-left panel-col panel-col-first\"><div class=\"inside\">\n" . $content["sidebar_left"] . "</div>\n</div>\n" . $output;
357 $css .= "$idcss div.panel-flexible-sidebars div.panel-sidebar-left { width: $size; margin-left: -$size; }\n";
358 $css .= "$idcss div.panel-flexible-sidebars { padding-left: $size; }\n";
359 // IE hack
360 $css .= "* html $idcss div.panel-flexible-sidebars div.panel-sidebar-left { left: $size; }\n";
361 }
362
363 if (!empty($settings['sidebars']['right'])) {
364 $size = intval($settings['sidebars']['right_width']) . $settings['sidebars']['width_type'];
365 $output .= "<div class=\"panel-sidebar panel-sidebar-right panel-col panel-col-last\"><div class=\"inside\">\n" . $content["sidebar_right"] . "</div>\n</div>\n";
366 $css .= "$idcss div.panel-flexible-sidebars div.panel-sidebar-right { width: $size; margin-right: -$size; }\n";
367 $css .= "$idcss div.panel-flexible-sidebars { padding-right: $size; }\n";
368 }
369
370 // Wrap the whole thing up nice and snug
371 $output = "<div class=\"panel-flexible clear-block\" $idstr>\n<div class=\"panel-flexible-sidebars\">\n" . $output . "</div>\n</div>\n";
372 drupal_set_html_head("<style type=\"text/css\" media=\"all\">\n$css</style>\n");
373 return $output;
374}
375