diff --git a/application/pdfpage.class.inc.php b/application/pdfpage.class.inc.php
index 56430f2852..84c58bfcc6 100644
--- a/application/pdfpage.class.inc.php
+++ b/application/pdfpage.class.inc.php
@@ -187,4 +187,10 @@ EOF
$this->flush();
echo $this->oPdf->Output($this->s_title.'.pdf', 'S');
}
+
+ public function get_pdf()
+ {
+ $this->flush();
+ return $this->oPdf->Output($this->s_title.'.pdf', 'S');
+ }
}
\ No newline at end of file
diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php
index fa205fdc60..19d96b5da5 100644
--- a/core/displayablegraph.class.inc.php
+++ b/core/displayablegraph.class.inc.php
@@ -879,8 +879,11 @@ class DisplayableGraph extends SimpleGraph
$fBreakMargin = $oPdf->getBreakMargin();
$oPdf->SetAutoPageBreak(false);
- $fKeyWidth = $this->RenderKey($oPdf, $sComments, $xMin, $yMin, $xMax, $yMax);
- $xMin += + $fKeyWidth;
+ $aRemainingArea = $this->RenderKey($oPdf, $sComments, $xMin, $yMin, $xMax, $yMax);
+ $xMin = $aRemainingArea['xmin'];
+ $xMax = $aRemainingArea['xmax'];
+ $yMin = $aRemainingArea['ymin'];
+ $yMax = $aRemainingArea['ymax'];
//$oPdf->Rect($xMin, $yMin, $xMax - $xMin, $yMax - $yMin, 'D', array(), array(225, 225, 225));
@@ -916,14 +919,15 @@ class DisplayableGraph extends SimpleGraph
}
/**
- * Renders (in PDF) the key (legend) of the graphics vertically to the left of the specified zone (xmin,ymin, xmax,ymax). Returns the width used by the legend.
+ * Renders (in PDF) the key (legend) of the graphics vertically to the left of the specified zone (xmin,ymin, xmax,ymax),
+ * and the comment (if any) at the bottom of the page. Returns the position of remaining area.
* @param TCPDF $oPdf
* @param string $sComments
* @param float $xMin
* @param float $yMin
* @param float $xMax
* @param float $yMax
- * @return number The width used by the legend
+ * @return hash An array ('xmin' => , 'xmax' => ,'ymin' => , 'ymax' => ) of the remaining available area to paint the graph
*/
protected function RenderKey(TCPDF $oPdf, $sComments, $xMin, $yMin, $xMax, $yMax)
{
@@ -963,15 +967,24 @@ class DisplayableGraph extends SimpleGraph
$oPdf->Image($aIcons[$sClass], $xMin+1, $yPos, $fIconSize, $fIconSize);
$yPos += $fIconSize + 2*$fPadding;
}
- $oPdf->Rect($xMin, $yMin, $fMaxWidth + $fIconSize + 3*$fPadding, $yPos - $yMin, 'D');
- $oPdf->Rect($xMin, $yPos, $fMaxWidth + $fIconSize + 3*$fPadding, $yMax - $yPos, 'D');
- $yPos +=1;
- $oPdf->SetXY($xMin + $fPadding, $yPos);
- $oPdf->Cell($fIconSize + $fPadding + $fMaxWidth, $fIconSize + $fPadding, Dict::S('UI:Relation:Comments'), 0 /* border */, 1 /* ln */, 'C', true /* fill */);
- $yPos += $fIconSize + 2*$fPadding;
- $oPdf->SetX($xMin);
- $oPdf->writeHTMLCell($fIconSize + 2*$fPadding + $fMaxWidth, $yMax - $yPos, $xMin, $yPos, '
'.str_replace("\n", '
', htmlentities($sComments, ENT_QUOTES, 'UTF-8')).'
', 0 /* border */, 1 /* ln */);
- return $fMaxWidth + $fIconSize + 4*$fPadding;
+ $oPdf->Rect($xMin, $yMin, $fMaxWidth + $fIconSize + 3*$fPadding, $yMax - $yMin, 'D');
+
+ if ($sComments != '')
+ {
+ // Draw the comment text (surrounded by a rectangle)
+ $xPos = $xMin + $fMaxWidth + $fIconSize + 4*$fPadding;
+ $w = $xMax - $xPos - 2*$fPadding;
+ $iNbLines = 1;
+ $sText = ''.str_replace("\n", '
', htmlentities($sComments, ENT_QUOTES, 'UTF-8'), $iNbLines).'
';
+ $fLineHeight = $oPdf->getStringHeight($w, $sText);
+ $h = (1+$iNbLines) * $fLineHeight;
+ $yPos = $yMax - 2*$fPadding - $h;
+ $oPdf->writeHTMLCell($w, $h, $xPos + $fPadding, $yPos + $fPadding, $sText, 0 /* border */, 1 /* ln */);
+ $oPdf->Rect($xPos, $yPos, $w + 2*$fPadding, $h + 2*$fPadding, 'D');
+ $yMax = $yPos - $fPadding;
+ }
+
+ return array('xmin' => $fMaxWidth + $fIconSize + 4*$fPadding, 'xmax' => $xMax, 'ymin' => $yMin, 'ymax' => $yMax);
}
/**
@@ -982,7 +995,7 @@ class DisplayableGraph extends SimpleGraph
* @param ApplicationContext $oAppContext
* @param array $aExcludedObjects
*/
- function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects = array())
+ function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects = array(), $sObjClass = null, $iObjKey = null)
{
$aExcludedByClass = array();
foreach($aExcludedObjects as $oObj)
@@ -1037,15 +1050,21 @@ EOF
{
$this->InitFromGraphviz();
$sExportAsPdfURL = '';
- if (extension_loaded('gd'))
- {
- $sExportAsPdfURL = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=relation_pdf&relation='.$sRelation.'&direction='.($this->bDirectionDown ? 'down' : 'up');
- }
+ $sExportAsPdfURL = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=relation_pdf&relation='.$sRelation.'&direction='.($this->bDirectionDown ? 'down' : 'up');
$oAppcontext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$sDrillDownURL = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class=%1$s&id=%2$s&'.$sContext;
- $sExportAsDocumentURL = '';
+ $sExportAsDocumentURL = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=relation_attachment&relation='.$sRelation.'&direction='.($this->bDirectionDown ? 'down' : 'up');
$sLoadFromURL = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=relation_json&relation='.$sRelation.'&direction='.($this->bDirectionDown ? 'down' : 'up');
+ $sAttachmentExportTitle = '';
+ if (($sObjClass != null) && ($iObjKey != null))
+ {
+ $oTargetObj = MetaModel::GetObject($sObjClass, $iObjKey, false);
+ if ($oTargetObj)
+ {
+ $sAttachmentExportTitle = Dict::Format('UI:Relation:AttachmentExportOptions_Name', $oTargetObj->GetName());
+ }
+ }
$sId = 'graph';
$oP->add('');
@@ -1055,13 +1074,15 @@ EOF
'excluded' => $aExcludedByClass,
'grouping_threshold' => $iGroupingThreshold,
'export_as_pdf' => array('url' => $sExportAsPdfURL, 'label' => Dict::S('UI:Relation:ExportAsPDF')),
- //'export_as_document' => array('url' => $sExportAsDocumentURL, 'label' => Dict::S('UI:Relation:ExportAsDocument')),
+ 'export_as_attachment' => array('url' => $sExportAsDocumentURL, 'label' => Dict::S('UI:Relation:ExportAsAttachment'), 'obj_class' => $sObjClass, 'obj_key' => $iObjKey),
'drill_down' => array('url' => $sDrillDownURL, 'label' => Dict::S('UI:Relation:DrillDown')),
'labels' => array(
'export_pdf_title' => Dict::S('UI:Relation:PDFExportOptions'),
+ 'export_as_attachment_title' => $sAttachmentExportTitle,
'export' => Dict::S('UI:Button:Export'),
'cancel' => Dict::S('UI:Button:Cancel'),
'title' => Dict::S('UI:RelationOption:Title'),
+ 'untitled' => Dict::S('UI:RelationOption:Untitled'),
'include_list' => Dict::S('UI:RelationOption:IncludeList'),
'comments' => Dict::S('UI:RelationOption:Comments'),
'grouping_threshold' => Dict::S('UI:RelationOption:GroupingThreshold'),
@@ -1083,6 +1104,17 @@ EOF
),
),
);
+ if (!extension_loaded('gd'))
+ {
+ // PDF export requires GD
+ unset($aParams['export_as_pdf']);
+ }
+ if (!extension_loaded('gd') || is_null($sObjClass) || is_null($iObjKey))
+ {
+ // PDF export requires GD AND a valid objclass/objkey couple
+ unset($aParams['export_as_pdf']);
+ unset($aParams['export_as_attachment']);
+ }
$oP->add_ready_script("$('#$sId').simple_graph(".json_encode($aParams).");");
}
catch(Exception $e)
diff --git a/dictionaries/de.dictionary.itop.ui.php b/dictionaries/de.dictionary.itop.ui.php
index 8df4bf7ca0..6e3e9bdd94 100644
--- a/dictionaries/de.dictionary.itop.ui.php
+++ b/dictionaries/de.dictionary.itop.ui.php
@@ -781,6 +781,8 @@ Wenn Aktionen mit Trigger verknüpft sind, bekommt jede Aktion eine Auftragsnumm
'UI:Relation:ExportAsDocument' => 'Export as Document...~~',
'UI:Relation:DrillDown' => 'Details...~~',
'UI:Relation:PDFExportOptions' => 'PDF Export Options~~',
+ 'UI:Relation:AttachmentExportOptions_Name' => 'Options for Attachment to %1$s~~',
+ 'UI:RelationOption:Untitled' => 'Untitled~~',
'UI:Relation:Key' => 'Key~~',
'UI:Relation:Comments' => 'Comments~~',
'UI:RelationOption:Title' => 'Title~~',
diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php
index 427e87f774..1be80e823d 100644
--- a/dictionaries/dictionary.itop.ui.php
+++ b/dictionaries/dictionary.itop.ui.php
@@ -971,9 +971,11 @@ When associated with a trigger, each action is given an "order" number, specifyi
'UI:RelationGroupNumber_N' => 'Group #%1$d',
'UI:Relation:ExportAsPDF' => 'Export as PDF...',
'UI:RelationOption:GroupingThreshold' => 'Grouping threshold',
- 'UI:Relation:ExportAsDocument' => 'Export as Document...',
+ 'UI:Relation:ExportAsAttachment' => 'Export as Attachment...',
'UI:Relation:DrillDown' => 'Details...',
'UI:Relation:PDFExportOptions' => 'PDF Export Options',
+ 'UI:Relation:AttachmentExportOptions_Name' => 'Options for Attachment to %1$s',
+ 'UI:RelationOption:Untitled' => 'Untitled',
'UI:Relation:Key' => 'Key',
'UI:Relation:Comments' => 'Comments',
'UI:RelationOption:Title' => 'Title',
diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php
index aa95460f47..4a7d1ac3ea 100644
--- a/dictionaries/fr.dictionary.itop.ui.php
+++ b/dictionaries/fr.dictionary.itop.ui.php
@@ -814,9 +814,11 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
'UI:RelationGroupNumber_N' => 'Groupe n°%1$d',
'UI:Relation:ExportAsPDF' => 'Exporter en PDF...',
'UI:RelationOption:GroupingThreshold' => 'Seuil de groupage',
- 'UI:Relation:ExportAsDocument' => 'Exporter comme Document...',
+ 'UI:Relation:ExportAsAttachment' => 'Exporter comme une Pièce Jointe...',
'UI:Relation:DrillDown' => 'Détails...',
'UI:Relation:PDFExportOptions' => 'Options de l\'export en PDF',
+ 'UI:Relation:AttachmentExportOptions_Name' => 'Options pour la Pièce Jointe à %1$s',
+ 'UI:RelationOption:Untitled' => 'Sans Titre',
'UI:Relation:Key' => 'Légende',
'UI:Relation:Comments' => 'Commentaires',
'UI:RelationOption:Title' => 'Titre',
diff --git a/js/simple_graph.js b/js/simple_graph.js
index c60d77443f..3f4589d8cf 100644
--- a/js/simple_graph.js
+++ b/js/simple_graph.js
@@ -33,7 +33,9 @@ $(function()
export_as_document: null,
drill_down: null,
grouping_threshold: 10,
- excluded_classes: []
+ excluded_classes: [],
+ attachment_obj_class: null,
+ attachment_obj_key: null
},
// the constructor
@@ -371,9 +373,9 @@ $(function()
{
sHtml += '';
}
- if (this.options.export_as_document != null)
+ if (this.options.export_as_attachment != null)
{
- sHtml += '';
+ sHtml += '';
}
//sHtml += '';
sHtml += '';
@@ -385,7 +387,7 @@ $(function()
var me = this;
$('#'+sPopupMenuId+'_pdf').click(function() { me.export_as_pdf(); });
- $('#'+sPopupMenuId+'_document').click(function() { me.export_as_document(); });
+ $('#'+sPopupMenuId+'_attachment').click(function() { me.export_as_attachment(); });
$('#'+sId+'_grouping_threshold').spinner({ min: 2});
$('#'+sId+'_refresh_btn').button().click(function() { me.reload(); });
},
@@ -449,13 +451,17 @@ $(function()
},
export_as_pdf: function()
+ {
+ this._export_dlg(this.options.labels.export_pdf_title, this.options.export_as_pdf.url, 'download_pdf');
+ },
+ _export_dlg: function(sTitle, sSubmitUrl, sOperation)
{
var oPositions = {};
for(k in this.aNodes)
{
oPositions[this.aNodes[k].id] = {x: this.aNodes[k].x, y: this.aNodes[k].y };
}
- var sHtmlForm = '