setClass ('table'); if (isset($style_name)) { $this->setStyleName ($style_name); } $this->setTableMaxColumns($maxcols); if ($maxcols == 0) { $this->setTableAutoColumns(true); } $this->container = new ODTContainerElement($this); } /** * Return the elements name. * * @return string The ODT XML element name. */ public function getElementName () { return ('table:table'); } /** * Return string with encoded opening tag. * * @return string The ODT XML code to open this element. */ public function getOpeningTag () { $style_name = $this->getStyleName(); if (!isset($style_name)) { $encoded = ''; } else { $encoded .= ''; } $maxcols = $this->getTableMaxColumns(); $count = $this->getCount(); if ($maxcols == 0) { // Try to automatically detect the number of columns. $this->setTableAutoColumns(true); } else { $this->setTableAutoColumns(false); } // Add column definitions placeholder. // This will be replaced on tabelClose()/getClosingTag() $encoded .= ''; // We start with the first column $this->setTableCurrentColumn(0); return $encoded; } /** * Return string with encoded closing tag. * * @return string The ODT XML code to close this element. */ public function getClosingTag (&$content = NULL) { // Generate table column definitions and replace the placeholder with it $count = $this->getCount(); $max = $this->getTableMaxColumns(); if ($max > 0 && isset($content)) { $column_defs = ''; for ($index = 0 ; $index < $max ; $index++) { $styleName = $this->getTableColumnStyleName($index); if (!empty($styleName)) { $column_defs .= ''; } else { $column_defs .= ''; } } $content = str_replace ('', $column_defs, $content); $content = str_replace ('', $max, $content); } return ''; } /** * Are we in a paragraph or not? * As a table we are not. * * @return boolean */ public function getInParagraph() { return false; } /** * Determine and set the parent for this element. * As a table the previous element is our parent. * * If the table is nested in another table, then the surrounding * table is the parent! * * @param ODTStateElement $previous */ public function determineParent(ODTStateElement $previous) { $this->container->determineParent($previous); if ($this->isNested ()) { $this->containerPos = array(); $this->getParent()->determinePositionInContainer($this->containerPos, $previous); } } /** * Set table column styles * * @param array $value */ public function setTableColumnStyles($value) { $this->table_column_styles = $value; } /** * Set table column style for $column * * @param array $value */ public function setTableColumnStyleName($column, $style_name) { $this->table_column_styles [$column] = $style_name; } /** * Get table column styles * * @return array */ public function getTableColumnStyles() { return $this->table_column_styles; } /** * Set table column style for $column * * @param array $value */ public function getTableColumnStyleName($column) { return $this->table_column_styles [$column]; } /** * Set flag if table columns shall be generated automatically. * (automatically detect the number of columns) * * @param boolean $value */ public function setTableAutoColumns($value) { $this->table_autocols = $value; } /** * Get flag if table columns shall be generated automatically. * (automatically detect the number of columns) * * @return boolean */ public function getTableAutoColumns() { return $this->table_autocols; } /** * Set maximal number of columns. * * @param integer $value */ public function setTableMaxColumns($value) { $this->table_maxcols = $value; } /** * Get maximal number of columns. * * @return integer */ public function getTableMaxColumns() { return $this->table_maxcols; } /** * Set current column. * * @param integer $value */ public function setTableCurrentColumn($value) { $this->table_curr_column = $value; } /** * Get current column. * * @return integer */ public function getTableCurrentColumn() { return $this->table_curr_column; } /** * Get the predefined style name for the current * table column. * * @return string */ public function getCurrentTableColumnStyleName() { $table_column_styles = $this->getTableColumnStyles(); $curr_column = $this->getTableCurrentColumn(); return $table_column_styles [$curr_column]; } /** * Set flag if current list is interrupted (by a table) or not. * * @param boolean $value */ public function setListInterrupted($value) { $this->list_interrupted = $value; } /** * Get flag if current list is interrupted (by a table) or not. * * @return boolean */ public function getListInterrupted() { return $this->list_interrupted; } /** * Increae the number of rows * * @param boolean $value */ public function increaseRowCount() { $this->table_row_count++; } public function getRowCount() { return $this->table_row_count; } /** * Is this table a nested table (inserted into another table)? * * @return boolean */ public function isNested () { return $this->container->isNested(); } public function addNestedContainer (iContainerAccess $nested) { $this->container->addNestedContainer ($nested); } public function getNestedContainers () { return $this->container->getNestedContainers (); } public function determinePositionInContainer (array &$data, ODTStateElement $current) { $data ['column'] = $this->getTableCurrentColumn(); $cell = NULL; while (isset($current)) { if ($current->getClass() == 'table-cell') { $cell = $current; break; } if ($current->getClass() == 'table') { break; } $current = $current->getParent(); } if (isset($cell)) { $data ['cell'] = $cell; } } public function getMaxWidthOfNestedContainer (ODTInternalParams $params, array $data) { if (!isset($this->own_max_width)) { // We do not know our own width yet. Calculate it first. $this->own_max_width = $this->getMaxWidth($params); } $column = $data ['column']; $cell = $data ['cell']; $cell_style = $cell->getStyle(); $padding = 0; if ($cell_style->getProperty('padding-left') != NULL || $cell_style->getProperty('padding-right') != NULL) { $value = $cell_style->getProperty('padding-left'); $value = $params->document->toPoints($value, 'y'); $padding += $value; $value = $cell_style->getProperty('padding-right'); $value = $params->document->toPoints($value, 'y'); $padding += $value; } else if ($cell_style->getProperty('padding') != NULL) { $value = $cell_style->getProperty('padding'); $value = $params->document->toPoints($value, 'y'); $padding += 2 * $value; } $table_column_styles = $this->getTableColumnStyles(); $style_name = $table_column_styles [$column-1]; $style_obj = $params->document->getStyle($style_name); if (isset($style_obj)) { $width = $style_obj->getProperty('column-width'); $width = trim ($width, 'pt'); $width -= $padding; } // Compare with total table width if (isset($this->own_max_width)) { $table_width = $params->units->getDigits ($params->units->toPoints($this->own_max_width)); if ($table_width < $width) { $width = $table_width; } } return $width.'pt'; } public function getMaxWidth (ODTInternalParams $params) { $tableStyle = $this->getStyle(); if (!$this->isNested ()) { // Get max page width in points. $maxPageWidth = $params->document->getAbsWidthMindMargins (); $maxPageWidthPt = $params->units->getDigits ($params->units->toPoints($maxPageWidth.'cm')); // Get table left margin $leftMargin = $tableStyle->getProperty('margin-left'); if (!isset($leftMargin)) { $leftMarginPt = 0; } else { $leftMarginPt = $params->units->getDigits ($params->units->toPoints($leftMargin)); } // Get table right margin $rightMargin = $tableStyle->getProperty('margin-right'); if (!isset($rightMargin)) { $rightMarginPt = 0; } else { $rightMarginPt = $params->units->getDigits ($params->units->toPoints($rightMargin)); } // Get table width $width = $tableStyle->getProperty('width'); if (isset($width)) { $widthPt = $params->units->getDigits ($params->units->toPoints($width)); } if (!isset($width)) { $width = $maxPageWidthPt - $leftMarginPt - $rightMarginPt; } else { $width = $widthPt; } $width = $width.'pt'; } else { // If this table is nested in another container we have to ask it's parent // for the allowed max width $width = $this->getParent()->getMaxWidthOfNestedContainer($params, $this->containerPos); } return $width; } /** * This function replaces the width of $table with the * value of all column width added together. If a column has * no width set then the function will abort and change nothing. * * @param ODTDocument $doc The current document * @param ODTElementTable $table The table to be adjusted */ public function adjustWidth (ODTInternalParams $params, $allowNested=false) { if ($this->isNested () && !$allowNested) { // Do not do anything if this is a nested table. // Only if the function is called for the parent/root table // then the width of the nested tables will be calculated. return; } $matches = array (); $table_style_name = $this->getStyleName(); if (empty($table_style_name)) { return; } $max_width = $this->getMaxWidth($params); $width = $this->adjustWidthInternal ($params, $max_width); $style_obj = $params->document->getStyle($table_style_name); if (isset($style_obj)) { $style_obj->setProperty('width', $width.'pt'); if (!$this->isNested ()) { // Calculate rel width in relation to maximum page width $maxPageWidth = $params->document->getAbsWidthMindMargins (); $maxPageWidth = $params->units->getDigits ($params->units->toPoints($maxPageWidth.'cm')); if ($maxPageWidth != 0) { $rel_width = round(($width * 100)/$maxPageWidth); } } else { // Calculate rel width in relation to maximum table width if ($max_width != 0) { $rel_width = round(($width * 100)/$max_width); } } $style_obj->setProperty('rel-width', $rel_width.'%'); } // Now adjust all nested containers too $nested = $this->getNestedContainers (); foreach ($nested as $container) { $container->adjustWidth ($params, true); } } public function adjustWidthInternal (ODTInternalParams $params, $maxWidth) { $empty = array(); $relative = array(); $anyWidthFound = false; $onlyAbsWidthFound = true; $tableStyle = $this->getStyle(); // First step: // - convert all absolute widths to points // - build the sum of all absolute column width values (if any) // - build the sum of all relative column width values (if any) $abs_sum = 0; $table_column_styles = $this->getTableColumnStyles(); $replace = true; for ($index = 0 ; $index < $this->getTableMaxColumns() ; $index++ ) { $style_name = $table_column_styles [$index]; $style_obj = $params->document->getStyle($style_name); if (isset($style_obj)) { if ($style_obj->getProperty('rel-column-width') != NULL) { $width = $style_obj->getProperty('rel-column-width'); $length = strlen ($width); $width = trim ($width, '*'); // Add column style object to relative array // We need convert it to an absolute width $entry = array(); $entry ['width'] = $width; $entry ['obj'] = $style_obj; $relative [] = $entry; $abs_sum += (($width/10)/100) * $maxWidth; $onlyAbsWidthFound = false; $anyWidthFound = true; } else if ($style_obj->getProperty('column-width') != NULL) { $width = $style_obj->getProperty('column-width'); $length = strlen ($width); $width = $params->document->toPoints($width, 'x'); $abs_sum += (float) trim ($width, 'pt'); $anyWidthFound = true; } else { // Add column style object to empty array // We need to assign a width to this column $empty [] = $style_obj; $onlyAbsWidthFound = false; } } } // Convert max width to points $maxWidth = $params->units->toPoints($maxWidth); $maxWidth = $params->units->getDigits($maxWidth); // The remaining absolute width is the max width minus the sum of // all absolute width values $absWidthLeft = $maxWidth - $abs_sum; // Calculate the relative width left // (e.g. if the absolute width is the half of the max width // then the relative width left if 50%) if ($maxWidth != 0) { $relWidthLeft = 100-(($absWidthLeft/$maxWidth)*100); } // Give all empty columns a width $maxEmpty = count($empty); foreach ($empty as $column) { //$width = ($relWidthLeft/$maxEmpty) * $absWidthLeft; $width = $absWidthLeft/$maxEmpty; $column->setProperty('column-width', $width.'pt'); $column->setProperty('rel-column-width', NULL); } // Convert all relative width to absolute foreach ($relative as $column) { $width = (($column ['width']/10)/100) * $maxWidth; $column ['obj']->setProperty('column-width', $width.'pt'); $column ['obj']->setProperty('rel-column-width', NULL); } // If all columns have a fixed absolute width set then that means // the table shall have the width of all comuns added together // and not the maximum available width. Return $abs_sum. if ($onlyAbsWidthFound && $anyWidthFound) { return $abs_sum; } return $maxWidth; } }