setClass ('frame'); if (isset($style_name)) { $this->setStyleName ($style_name); } $this->container = new ODTContainerElement($this); } /** * Return the elements name. * * @return string The ODT XML element name. */ public function getElementName () { return ('draw:frame'); } /** * Return string with encoded opening tag. * * @return string The ODT XML code to open this element. */ public function getOpeningTag (ODTInternalParams $params=NULL) { // Convert width to points $width = $this->getWidth(); if (isset($width)) { $width = $params->units->toPoints($width); $this->setWidth($width); } $encoded = 'getAttributes().'>'; $this->written = true; return $encoded; } /** * Return string with encoded closing tag. * * @return string The ODT XML code to close this element. */ public function getClosingTag () { return ''; } /** * Are we in a paragraph or not? * As a frame we are not. * * @return boolean */ public function getInParagraph() { return false; } /** * Determine and set the parent for this element. * As a frame the previous element is our 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); } //$this->setParent($previous); } /** * Set frame attributes * * @param array $value */ public function setAttributes($value) { // Delete linebreaks and multiple whitespace $this->attributes = preg_replace( "/\r|\n/", "", $value); $this->attributes = preg_replace( "/\s+/", " ", $this->attributes); // Save name for later width rewriting $this->nameAttr = $this->getNameAttribute(); $this->name = $this->getName(); } /** * Get frame attributes * * @return array */ public function getAttributes() { return $this->attributes; } /** * Is this frame a nested frame (inserted into another table/frame)? * * @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) { // Position in frame doesn't mater for width calculation // So this is a dummy for now $data ['frame'] = true; } 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); // Re-Write our width if frame already has been written to the document if ($this->written) { if (preg_match('/nameAttr.'[^>]*>/', $params->content, $matches) === 1) { $frameTag = $matches [0]; $frameTag = preg_replace('/svg:width="[^"]*"/', 'svg:width="'.$this->own_max_width.'"', $frameTag); // Replace old frame tag in document in $params->content = str_replace ($matches [0], $frameTag, $params->content); } } } // Convert to points if (isset($this->own_max_width)) { $width = $params->units->getDigits ($params->units->toPoints($this->own_max_width)); } return $width.'pt'; } public function getMaxWidth (ODTInternalParams $params) { if (isset($this->own_max_width)) { return $this->own_max_width; } $frameStyle = $this->getStyle(); // Get frame left margin $leftMargin = $frameStyle->getProperty('margin-left'); if (!isset($leftMargin)) { $leftMarginPt = 0; } else { $leftMarginPt = $params->units->getDigits ($params->units->toPoints($leftMargin)); } // Get frame right margin $rightMargin = $frameStyle->getProperty('margin-right'); if (!isset($rightMargin)) { $rightMarginPt = 0; } else { $rightMarginPt = $params->units->getDigits ($params->units->toPoints($rightMargin)); } // Get available max width if (!$this->isNested ()) { // Get max page width in points. $maxWidth = $params->document->getAbsWidthMindMargins (); $maxWidthPt = $params->units->getDigits ($params->units->toPoints($maxWidth.'cm')); } else { // If this frame is nested in another container we have to ask it's parent // for the allowed max width $maxWidth = $this->getParent()->getMaxWidthOfNestedContainer($params, $this->containerPos); $maxWidthPt = $params->units->getDigits ($params->units->toPoints($maxWidth)); } // Get frame width $width = $this->getWidth(); if (isset($width)) { if ($width [strlen($width)-1] != '%') { $widthPt = $params->units->getDigits ($params->units->toPoints($width)); } else { $percentage = trim ($width, '%'); $widthPt = ($percentage * $maxWidthPt)/100; } } // Calculate final width. // If no frame width is set or the frame width is greater than // the calculated max width then use the max width. $maxWidthPt = $maxWidthPt - $leftMarginPt - $rightMarginPt; if (!isset($width) || $widthPt > $maxWidthPt) { $width = $maxWidthPt - $leftMarginPt - $rightMarginPt; } else { $width = $widthPt; } $width = $width.'pt'; return $width; } public function getWidth() { if (isset($this->attributes)) { if ( preg_match('/svg:width="[^"]+"/', $this->attributes, $matches) === 1 ) { $width = substr ($matches [0], 11); $width = trim ($width, '"'); return $width; } } return NULL; } public function setWidth($width) { if (isset($this->attributes)) { if ( preg_match('/svg:width="[^"]+"/', $this->attributes, $matches) === 1 ) { $widthAttr = 'svg:width="'.$width.'"'; $this->attributes = str_replace($matches [0], $widthAttr, $this->attributes); return; } } $this->attributes .= ' svg:width="'.$width.'"'; } public function getNameAttribute() { if (isset($this->attributes)) { if ( preg_match('/draw:name="[^"]+"/', $this->attributes, $matches) === 1 ) { return $matches [0]; } } return NULL; } public function getName() { if (isset($this->attributes)) { if ( preg_match('/draw:name="[^"]+"/', $this->attributes, $matches) === 1 ) { $name = substr ($matches [0], 10); $name = trim ($name, '"'); return $name; } } return NULL; } /** * This function adjust the width of the frame. * There is not much to do except conversion of relative to absolute values * and calling the method for all nested elements. * (table has got more work to do, see ODTElementTable::adjustWidth) * * @param ODTInternalParams $params Common ODT params * @param boolean $allowNested Allow to process call if this frame is nested */ 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 (); $max_width = $this->getMaxWidth($params); //FIXME: convert % to points // Now adjust all nested containers too $nested = $this->getNestedContainers (); foreach ($nested as $container) { $container->adjustWidth ($params, true); } } }